diff options
author | stanleyk <stanleyk@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2013-02-05 21:11:03 +0000 |
---|---|---|
committer | stanleyk <stanleyk@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2013-02-05 21:11:03 +0000 |
commit | 5e030faf84086ab02059fcbcc3faed224bd57b95 (patch) | |
tree | 3a62df45ac6ccf599fb07cf6a03d672456ce2e3d /TAO/tao | |
parent | 9d296f7fa51116ff7040ecb2ad18612cd94b5fd1 (diff) | |
download | ATCD-5e030faf84086ab02059fcbcc3faed224bd57b95.tar.gz |
Merge in OCI_Reliability_Enhancements branch.
Diffstat (limited to 'TAO/tao')
104 files changed, 7002 insertions, 576 deletions
diff --git a/TAO/tao/AnyTypeCode/Struct_TypeCode.cpp b/TAO/tao/AnyTypeCode/Struct_TypeCode.cpp index b920fd9f483..0418ed99896 100644 --- a/TAO/tao/AnyTypeCode/Struct_TypeCode.cpp +++ b/TAO/tao/AnyTypeCode/Struct_TypeCode.cpp @@ -108,6 +108,19 @@ template <typename StringType, typename TypeCodeType, class FieldArrayType, class RefCountPolicy> +const FieldArrayType& +TAO::TypeCode::Struct<StringType, + TypeCodeType, + FieldArrayType, + RefCountPolicy>::fields (void) const +{ + return fields_; +} + +template <typename StringType, + typename TypeCodeType, + class FieldArrayType, + class RefCountPolicy> CORBA::Boolean TAO::TypeCode::Struct<StringType, TypeCodeType, diff --git a/TAO/tao/AnyTypeCode/Struct_TypeCode.h b/TAO/tao/AnyTypeCode/Struct_TypeCode.h index 422b6b3fdf8..27ede78e202 100644 --- a/TAO/tao/AnyTypeCode/Struct_TypeCode.h +++ b/TAO/tao/AnyTypeCode/Struct_TypeCode.h @@ -78,6 +78,9 @@ namespace TAO virtual void tao_release (void); //@} + /// Accessor for fields_ + const FieldArrayType& fields() const; + protected: /** diff --git a/TAO/tao/AnyTypeCode/TypeCode_CDR_Extraction.cpp b/TAO/tao/AnyTypeCode/TypeCode_CDR_Extraction.cpp index 661e8414d57..6e05e19bfd1 100644 --- a/TAO/tao/AnyTypeCode/TypeCode_CDR_Extraction.cpp +++ b/TAO/tao/AnyTypeCode/TypeCode_CDR_Extraction.cpp @@ -60,7 +60,7 @@ namespace TAO namespace { - bool add_to_recursion_list (CORBA::TypeCode_ptr & tc, + bool add_to_tc_info_list (CORBA::TypeCode_ptr & tc, TAO::TypeCodeFactory::TC_Info_List & infos) { // Since we created a new tc, add it to the list. @@ -127,24 +127,30 @@ namespace // Use an ACE::Value_Ptr to provide exception safety and proper // copying semantics. - typedef ACE::Value_Ptr<TAO::TypeCode::Case<CORBA::String_var, CORBA::TypeCode_var> > union_elem_type; + typedef ACE::Value_Ptr<TAO::TypeCode::Case<CORBA::String_var, + CORBA::TypeCode_var> > union_elem_type; typedef ACE_Array_Base<union_elem_type> union_case_array_type; // ------------------------------------------------------------ /// Demarshal a TypeCode. - bool tc_demarshal (TAO_InputCDR & cdr, - CORBA::TypeCode_ptr & tc, - TAO::TypeCodeFactory::TC_Info_List & infos); + bool tc_demarshal ( + TAO_InputCDR & cdr, + CORBA::TypeCode_ptr & tc, + TAO::TypeCodeFactory::TC_Info_List & indirect_infos, + TAO::TypeCodeFactory::TC_Info_List & direct_infos); /// Demarshal an indirected TypeCode. - bool tc_demarshal_indirection (TAO_InputCDR & cdr, - CORBA::TypeCode_ptr & tc, - TAO::TypeCodeFactory::TC_Info_List & infos); - - bool find_recursive_tc (char const * id, - TAO::TypeCodeFactory::TC_Info_List & tcs, - TAO::TypeCodeFactory::TC_Info_List & infos) + bool tc_demarshal_indirection ( + TAO_InputCDR & cdr, + CORBA::TypeCode_ptr & tc, + TAO::TypeCodeFactory::TC_Info_List & indirect_infos, + TAO::TypeCodeFactory::TC_Info_List & direct_infos); + + bool find_recursive_tc ( + char const * id, + TAO::TypeCodeFactory::TC_Info_List & tcs, + TAO::TypeCodeFactory::TC_Info_List & infos) { // See comments above for rationale behind using an array instead // of a map. @@ -170,12 +176,25 @@ namespace return (tcs.size () > 0) ; } + + // For TC_Info_List whose elements are duplicated prior to addition, + // clean up the list by calling release on the typecode pointers. + void cleanup_tc_info_list (TAO::TypeCodeFactory::TC_Info_List & infos) + { + size_t const len = infos.size (); + + for (size_t i = 0; i < len; ++i) + { + CORBA::release(infos[i].type); + } + } } bool TAO::TypeCodeFactory::tc_null_factory (CORBA::TCKind, TAO_InputCDR &, CORBA::TypeCode_ptr & tc, + TC_Info_List &, TC_Info_List &) { tc = CORBA::TypeCode::_duplicate (CORBA::_tc_null); @@ -187,6 +206,7 @@ bool TAO::TypeCodeFactory::tc_void_factory (CORBA::TCKind, TAO_InputCDR &, CORBA::TypeCode_ptr & tc, + TC_Info_List &, TC_Info_List &) { tc = CORBA::TypeCode::_duplicate (CORBA::_tc_void); @@ -198,6 +218,7 @@ bool TAO::TypeCodeFactory::tc_short_factory (CORBA::TCKind, TAO_InputCDR &, CORBA::TypeCode_ptr & tc, + TC_Info_List &, TC_Info_List &) { tc = CORBA::TypeCode::_duplicate (CORBA::_tc_short); @@ -209,6 +230,7 @@ bool TAO::TypeCodeFactory::tc_long_factory (CORBA::TCKind, TAO_InputCDR &, CORBA::TypeCode_ptr & tc, + TC_Info_List &, TC_Info_List &) { tc = CORBA::TypeCode::_duplicate (CORBA::_tc_long); @@ -220,6 +242,7 @@ bool TAO::TypeCodeFactory::tc_ushort_factory (CORBA::TCKind, TAO_InputCDR &, CORBA::TypeCode_ptr & tc, + TC_Info_List &, TC_Info_List &) { tc = CORBA::TypeCode::_duplicate (CORBA::_tc_ushort); @@ -231,6 +254,7 @@ bool TAO::TypeCodeFactory::tc_ulong_factory (CORBA::TCKind, TAO_InputCDR &, CORBA::TypeCode_ptr & tc, + TC_Info_List &, TC_Info_List &) { tc = CORBA::TypeCode::_duplicate (CORBA::_tc_ulong); @@ -242,6 +266,7 @@ bool TAO::TypeCodeFactory::tc_float_factory (CORBA::TCKind, TAO_InputCDR &, CORBA::TypeCode_ptr & tc, + TC_Info_List &, TC_Info_List &) { tc = CORBA::TypeCode::_duplicate (CORBA::_tc_float); @@ -253,6 +278,7 @@ bool TAO::TypeCodeFactory::tc_double_factory (CORBA::TCKind, TAO_InputCDR &, CORBA::TypeCode_ptr & tc, + TC_Info_List &, TC_Info_List &) { tc = CORBA::TypeCode::_duplicate (CORBA::_tc_double); @@ -264,6 +290,7 @@ bool TAO::TypeCodeFactory::tc_boolean_factory (CORBA::TCKind, TAO_InputCDR &, CORBA::TypeCode_ptr & tc, + TC_Info_List &, TC_Info_List &) { tc = CORBA::TypeCode::_duplicate (CORBA::_tc_boolean); @@ -275,6 +302,7 @@ bool TAO::TypeCodeFactory::tc_char_factory (CORBA::TCKind, TAO_InputCDR &, CORBA::TypeCode_ptr & tc, + TC_Info_List &, TC_Info_List &) { tc = CORBA::TypeCode::_duplicate (CORBA::_tc_char); @@ -286,6 +314,7 @@ bool TAO::TypeCodeFactory::tc_octet_factory (CORBA::TCKind, TAO_InputCDR &, CORBA::TypeCode_ptr & tc, + TC_Info_List &, TC_Info_List &) { tc = CORBA::TypeCode::_duplicate (CORBA::_tc_octet); @@ -297,6 +326,7 @@ bool TAO::TypeCodeFactory::tc_any_factory (CORBA::TCKind, TAO_InputCDR &, CORBA::TypeCode_ptr & tc, + TC_Info_List &, TC_Info_List &) { tc = CORBA::TypeCode::_duplicate (CORBA::_tc_any); @@ -308,6 +338,7 @@ bool TAO::TypeCodeFactory::tc_TypeCode_factory (CORBA::TCKind, TAO_InputCDR &, CORBA::TypeCode_ptr & tc, + TC_Info_List &, TC_Info_List &) { tc = CORBA::TypeCode::_duplicate (CORBA::_tc_TypeCode); @@ -319,6 +350,7 @@ bool TAO::TypeCodeFactory::tc_Principal_factory (CORBA::TCKind, TAO_InputCDR &, CORBA::TypeCode_ptr & tc, + TC_Info_List &, TC_Info_List &) { tc = CORBA::TypeCode::_duplicate (CORBA::_tc_Principal); @@ -330,6 +362,7 @@ bool TAO::TypeCodeFactory::tc_objref_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, + TC_Info_List &, TC_Info_List &) { // The remainder of a tk_objref TypeCode is encoded in a CDR @@ -343,11 +376,14 @@ TAO::TypeCodeFactory::tc_objref_factory (CORBA::TCKind kind, if (!(cdr >> TAO_InputCDR::to_string (id.out (), 0))) return false; - static char const Object_id[] = "IDL:omg.org/CORBA/Object:1.0"; - static char const CCMObject_id[] = "IDL:omg.org/CORBA/CCMObject:1.0"; - static char const CCMHome_id[] = "IDL:omg.org/CORBA/CCMHome:1.0"; + static char const Object_id[] = + ACE_TEXT_ALWAYS_CHAR ("IDL:omg.org/CORBA/Object:1.0"); + static char const CCMObject_id[] = + ACE_TEXT_ALWAYS_CHAR ("IDL:omg.org/CORBA/CCMObject:1.0"); + static char const CCMHome_id[] = + ACE_TEXT_ALWAYS_CHAR ("IDL:omg.org/CORBA/CCMHome:1.0"); - char const * tc_constant_id = ""; + char const * tc_constant_id = ACE_TEXT_ALWAYS_CHAR (""); switch (kind) { @@ -415,7 +451,8 @@ bool TAO::TypeCodeFactory::tc_struct_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos) + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos) { ACE_ASSERT (kind == CORBA::tk_struct || kind == CORBA::tk_except); @@ -443,7 +480,10 @@ TAO::TypeCodeFactory::tc_struct_factory (CORBA::TCKind kind, for (CORBA::ULong i = 0; i < nfields; ++i) { if (!(cdr >> TAO_InputCDR::to_string (fields[i].name.out (), 0) - && tc_demarshal (cdr, fields[i].type.out (), infos))) + && tc_demarshal (cdr, + fields[i].type.out (), + indirect_infos, + direct_infos))) return false; } @@ -455,7 +495,9 @@ TAO::TypeCodeFactory::tc_struct_factory (CORBA::TCKind kind, // Check if struct TypeCode is recursive. TAO::TypeCodeFactory::TC_Info_List recursive_tc; - if (kind == CORBA::tk_struct && find_recursive_tc (id.in (), recursive_tc, infos)) + if (kind == CORBA::tk_struct && find_recursive_tc (id.in (), + recursive_tc, + indirect_infos)) { // Set remaining parameters. typedef TAO::TypeCode::Recursive_Type<typecode_type, @@ -476,7 +518,9 @@ TAO::TypeCodeFactory::tc_struct_factory (CORBA::TCKind kind, if (!rtc) return false; // Should never occur. - assigned_params |= rtc->struct_parameters (name.in (), fields, nfields); + assigned_params |= rtc->struct_parameters (name.in (), + fields, + nfields); } // If no parameters were assigned then the reference in the @@ -502,6 +546,10 @@ TAO::TypeCodeFactory::tc_struct_factory (CORBA::TCKind kind, false); } + CORBA::TypeCode_ptr dup_tc = CORBA::TypeCode::_duplicate(tc); + if (!add_to_tc_info_list(dup_tc, direct_infos)) { + return false; + } return true; } @@ -509,7 +557,8 @@ bool TAO::TypeCodeFactory::tc_union_factory (CORBA::TCKind /* kind */, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos) + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos) { // The remainder of a tk_enum TypeCode is encoded in a CDR // encapsulation. @@ -559,7 +608,8 @@ TAO::TypeCodeFactory::tc_union_factory (CORBA::TCKind /* kind */, { elem_type & member = cases[i]; - TAO::TypeCode::Case<CORBA::String_var, CORBA::TypeCode_var> * the_case = 0; + TAO::TypeCode::Case<CORBA::String_var, CORBA::TypeCode_var> * + the_case = 0; // Ugly. *sigh* switch (discriminant_kind) @@ -709,7 +759,9 @@ TAO::TypeCodeFactory::tc_union_factory (CORBA::TCKind /* kind */, CORBA::TypeCode_var the_type; if (!(cdr >> TAO_InputCDR::to_string (the_name.out (), 0) - && tc_demarshal (cdr, the_type.out (), infos))) + && tc_demarshal (cdr, the_type.out (), + indirect_infos, + direct_infos))) return false; member->name (the_name.in ()); @@ -723,7 +775,7 @@ TAO::TypeCodeFactory::tc_union_factory (CORBA::TCKind /* kind */, // Check if we have recursive members. There could be multiple. TAO::TypeCodeFactory::TC_Info_List recursive_tc; - if (find_recursive_tc (id.in (), recursive_tc, infos)) + if (find_recursive_tc (id.in (), recursive_tc, indirect_infos)) { // Set remaining parameters. @@ -777,6 +829,10 @@ TAO::TypeCodeFactory::tc_union_factory (CORBA::TCKind /* kind */, false); } + CORBA::TypeCode_ptr dup_tc = CORBA::TypeCode::_duplicate(tc); + if (!add_to_tc_info_list(dup_tc, direct_infos)) { + return false; + } return true; } @@ -784,6 +840,7 @@ bool TAO::TypeCodeFactory::tc_enum_factory (CORBA::TCKind /* kind */, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, + TC_Info_List &, TC_Info_List &) { // The remainder of a tk_enum TypeCode is encoded in a CDR @@ -828,6 +885,7 @@ bool TAO::TypeCodeFactory::tc_string_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, + TC_Info_List &, TC_Info_List &) { // A tk_string/tk_wstring TypeCode has a simple parameter list, @@ -863,7 +921,8 @@ bool TAO::TypeCodeFactory::tc_sequence_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos) + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos) { ACE_ASSERT (kind == CORBA::tk_sequence || kind == CORBA::tk_array); @@ -877,7 +936,7 @@ TAO::TypeCodeFactory::tc_sequence_factory (CORBA::TCKind kind, CORBA::TypeCode_var content_type; CORBA::ULong length; - if (!(tc_demarshal (cdr, content_type.out (), infos) + if (!(tc_demarshal (cdr, content_type.out (), indirect_infos, direct_infos) && cdr >> length)) return false; @@ -896,16 +955,18 @@ bool TAO::TypeCodeFactory::tc_array_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos) + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos) { - return tc_sequence_factory (kind, cdr, tc, infos); + return tc_sequence_factory (kind, cdr, tc, indirect_infos, direct_infos); } bool TAO::TypeCodeFactory::tc_alias_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos) + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos) { // The remainder of a tk_alias or tk_value_box TypeCode is encoded // in a CDR encapsulation. @@ -918,7 +979,10 @@ TAO::TypeCodeFactory::tc_alias_factory (CORBA::TCKind kind, CORBA::TypeCode_var content_type; if (!(cdr >> TAO_InputCDR::to_string (id.out (), 0) && cdr >> TAO_InputCDR::to_string (name.out (), 0) - && tc_demarshal (cdr, content_type.out (), infos))) + && tc_demarshal (cdr, + content_type.out (), + indirect_infos, + direct_infos))) { return false; } @@ -941,15 +1005,17 @@ bool TAO::TypeCodeFactory::tc_except_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos) + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos) { - return tc_struct_factory (kind, cdr, tc, infos); + return tc_struct_factory (kind, cdr, tc, indirect_infos, direct_infos); } bool TAO::TypeCodeFactory::tc_longlong_factory (CORBA::TCKind, TAO_InputCDR &, CORBA::TypeCode_ptr & tc, + TC_Info_List &, TC_Info_List &) { tc = CORBA::TypeCode::_duplicate (CORBA::_tc_longlong); @@ -961,6 +1027,7 @@ bool TAO::TypeCodeFactory::tc_ulonglong_factory (CORBA::TCKind, TAO_InputCDR &, CORBA::TypeCode_ptr & tc, + TC_Info_List &, TC_Info_List &) { tc = CORBA::TypeCode::_duplicate (CORBA::_tc_ulonglong); @@ -972,6 +1039,7 @@ bool TAO::TypeCodeFactory::tc_longdouble_factory (CORBA::TCKind, TAO_InputCDR &, CORBA::TypeCode_ptr & tc, + TC_Info_List &, TC_Info_List &) { tc = CORBA::TypeCode::_duplicate (CORBA::_tc_longdouble); @@ -983,6 +1051,7 @@ bool TAO::TypeCodeFactory::tc_wchar_factory (CORBA::TCKind, TAO_InputCDR &, CORBA::TypeCode_ptr & tc, + TC_Info_List &, TC_Info_List &) { tc = CORBA::TypeCode::_duplicate (CORBA::_tc_wchar); @@ -994,15 +1063,17 @@ bool TAO::TypeCodeFactory::tc_wstring_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos) + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos) { - return tc_string_factory (kind, cdr, tc, infos); + return tc_string_factory (kind, cdr, tc, indirect_infos, direct_infos); } bool TAO::TypeCodeFactory::tc_fixed_factory (CORBA::TCKind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, + TC_Info_List &, TC_Info_List &) { // A tk_fixed TypeCode has a simple parameter list, i.e. it is not @@ -1025,7 +1096,8 @@ bool TAO::TypeCodeFactory::tc_value_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos) + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos) { // The remainder of a tk_value/tk_event TypeCode is encoded in a // CDR encapsulation @@ -1061,7 +1133,7 @@ TAO::TypeCodeFactory::tc_value_factory (CORBA::TCKind kind, CORBA::TypeCode_var> & field = fields[i]; if (!(cdr >> TAO_InputCDR::to_string (field.name.out (), 0) - && tc_demarshal (cdr, field.type.out (), infos) + && tc_demarshal (cdr, field.type.out (), indirect_infos, direct_infos) && cdr >> field.visibility)) return false; } @@ -1074,7 +1146,7 @@ TAO::TypeCodeFactory::tc_value_factory (CORBA::TCKind kind, // Check if valuetype/eventtype TypeCode is recursive. TAO::TypeCodeFactory::TC_Info_List recursive_tc; - if (find_recursive_tc (id.in (), recursive_tc, infos)) + if (find_recursive_tc (id.in (), recursive_tc, indirect_infos)) { // Set remaining parameters. @@ -1127,6 +1199,10 @@ TAO::TypeCodeFactory::tc_value_factory (CORBA::TCKind kind, false); } + CORBA::TypeCode_ptr dup_tc = CORBA::TypeCode::_duplicate(tc); + if (!add_to_tc_info_list(dup_tc, direct_infos)) { + return false; + } return true; } @@ -1134,63 +1210,74 @@ bool TAO::TypeCodeFactory::tc_value_box_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos) + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos) { - return tc_alias_factory (kind, cdr, tc, infos); + return tc_alias_factory (kind, cdr, tc, indirect_infos, direct_infos); } bool TAO::TypeCodeFactory::tc_native_factory (CORBA::TCKind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos) + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos) { - return tc_objref_factory (CORBA::tk_native, cdr, tc, infos); + return tc_objref_factory (CORBA::tk_native, cdr, tc, indirect_infos, direct_infos); } bool TAO::TypeCodeFactory::tc_abstract_interface_factory (CORBA::TCKind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos) + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos) { - return tc_objref_factory (CORBA::tk_abstract_interface, cdr, tc, infos); + return tc_objref_factory (CORBA::tk_abstract_interface, + cdr, + tc, + indirect_infos, + direct_infos); } bool TAO::TypeCodeFactory::tc_local_interface_factory (CORBA::TCKind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos) + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos) { - return tc_objref_factory (CORBA::tk_local_interface, cdr, tc, infos); + return tc_objref_factory (CORBA::tk_local_interface, cdr, tc, indirect_infos, direct_infos); } bool TAO::TypeCodeFactory::tc_component_factory (CORBA::TCKind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos) + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos) { - return tc_objref_factory (CORBA::tk_component, cdr, tc, infos); + return tc_objref_factory (CORBA::tk_component, cdr, tc, indirect_infos, direct_infos); } bool TAO::TypeCodeFactory::tc_home_factory (CORBA::TCKind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos) + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos) { - return tc_objref_factory (CORBA::tk_home, cdr, tc, infos); + return tc_objref_factory (CORBA::tk_home, cdr, tc, indirect_infos, direct_infos); } bool TAO::TypeCodeFactory::tc_event_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos) + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos) { - return tc_value_factory (kind, cdr, tc, infos); + return tc_value_factory (kind, cdr, tc, indirect_infos, direct_infos); } // --------------------------------------------------------------- @@ -1200,7 +1287,8 @@ namespace bool tc_demarshal (TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TAO::TypeCodeFactory::TC_Info_List & infos) + TAO::TypeCodeFactory::TC_Info_List & indirect_infos, + TAO::TypeCodeFactory::TC_Info_List & direct_infos) { // ULong since we need to detect indirected TypeCodes, too. @@ -1210,8 +1298,9 @@ namespace && kind != TYPECODE_INDIRECTION)) return false; - if (kind == TYPECODE_INDIRECTION) - return tc_demarshal_indirection (cdr, tc, infos); + if (kind == TYPECODE_INDIRECTION) { + return tc_demarshal_indirection (cdr, tc, indirect_infos, direct_infos); + } using namespace TAO::TypeCodeFactory; @@ -1259,13 +1348,16 @@ namespace return factory_map[kind] (static_cast<CORBA::TCKind> (kind), cdr, tc, - infos); + indirect_infos, + direct_infos); } bool - tc_demarshal_indirection (TAO_InputCDR & cdr, - CORBA::TypeCode_ptr & tc, - TAO::TypeCodeFactory::TC_Info_List & infos) + tc_demarshal_indirection ( + TAO_InputCDR & cdr, + CORBA::TypeCode_ptr & tc, + TAO::TypeCodeFactory::TC_Info_List & indirect_infos, + TAO::TypeCodeFactory::TC_Info_List & direct_infos) { CORBA::Long offset; @@ -1332,7 +1424,10 @@ namespace CORBA::String_var name; CORBA::TypeCode_var content_type; if (!(indir_stream >> TAO_InputCDR::to_string (name.out (), 0) - && tc_demarshal (indir_stream, content_type.out (), infos))) + && tc_demarshal (indir_stream, + content_type.out (), + indirect_infos, + direct_infos))) { return false; } @@ -1357,7 +1452,7 @@ namespace // Check if we already have a tc for this RECURSIVE type, if yes, use that TAO::TypeCodeFactory::TC_Info_List recursive_tc; - if (find_recursive_tc (id.in (), recursive_tc, infos)) + if (find_recursive_tc (id.in (), recursive_tc, indirect_infos)) { tc = CORBA::TypeCode::_duplicate(recursive_tc[0].type); } @@ -1386,8 +1481,9 @@ namespace id.in ()), false); - // Since we created a new recursive tc, add it to the "Recursive" list. - return add_to_recursion_list (tc, infos); + // Since we created a new recursive tc, add it to + // the "Recursive" list. + return add_to_tc_info_list (tc, indirect_infos); } break; case CORBA::tk_union: @@ -1410,8 +1506,9 @@ namespace id.in ()), false); - // Since we created a new recursive tc, add it to the "Recursive" list. - return add_to_recursion_list (tc, infos); + // Since we created a new recursive tc, add it + // to the "Recursive" list. + return add_to_tc_info_list (tc, indirect_infos); } break; case CORBA::tk_value: @@ -1438,8 +1535,9 @@ namespace id.in ()), false); - // Since we created a new recursive tc, add it to the "Recursive" list. - return add_to_recursion_list (tc, infos); + // Since we created a new recursive tc, add it + // to the "Recursive" list. + return add_to_tc_info_list (tc, indirect_infos); } break; default: @@ -1455,9 +1553,146 @@ namespace CORBA::Boolean operator>> (TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc) { - TAO::TypeCodeFactory::TC_Info_List infos; + TAO::TypeCodeFactory::TC_Info_List indirect_infos; + TAO::TypeCodeFactory::TC_Info_List direct_infos; + + if (!tc_demarshal (cdr, tc, indirect_infos, direct_infos)) { + cleanup_tc_info_list(direct_infos); + return false; + } + + if (indirect_infos.size() == 0) { + cleanup_tc_info_list(direct_infos); + return true; + } + + for (size_t i = 0; i < direct_infos.size(); ++i) { + CORBA::TypeCode_ptr& tc = direct_infos[i].type; + + TAO::TypeCodeFactory::TC_Info_List recursive_tc; + if (find_recursive_tc(tc->id(), recursive_tc, indirect_infos)) { + size_t const len = recursive_tc.size (); + bool assigned_params = false; + + switch (tc->kind()) { + case CORBA::tk_struct: + { + // Set remaining parameters. + typedef ACE_Array_Base<TAO::TypeCode::Struct_Field<CORBA::String_var, + CORBA::TypeCode_var> > + member_array_type; + + typedef TAO::TypeCode::Struct< + CORBA::String_var, + CORBA::TypeCode_var, + member_array_type, + TAO::True_RefCount_Policy> typecode_type; + + typedef TAO::TypeCode::Recursive_Type<typecode_type, + CORBA::TypeCode_var, + member_array_type> + recursive_typecode_type; + + typecode_type * const tc_struct = dynamic_cast<typecode_type *>(tc); + for (size_t i = 0; i < len; ++i) + { + TAO::TypeCodeFactory::TC_Info & info = recursive_tc[i]; + + recursive_typecode_type * const rtc = + dynamic_cast<recursive_typecode_type *> (info.type); + + if (!rtc) + return false; // Should never occur. + + assigned_params |= rtc->struct_parameters ( + tc_struct->name(), + tc_struct->fields(), + tc_struct->member_count()); + } + } + break; + case CORBA::tk_union: + { + // Set remaining parameters. + typedef union_case_array_type case_array_type; + + typedef TAO::TypeCode::Union<CORBA::String_var, + CORBA::TypeCode_var, + case_array_type, + TAO::True_RefCount_Policy> + typecode_type; + + typedef TAO::TypeCode::Recursive_Type<typecode_type, + CORBA::TypeCode_var, + case_array_type> + recursive_typecode_type; + + typecode_type * const tc_union = dynamic_cast<typecode_type *>(tc); + for (size_t i = 0; i < len; ++i) + { + TAO::TypeCodeFactory::TC_Info & info = recursive_tc[i]; + + recursive_typecode_type * const rtc = + dynamic_cast<recursive_typecode_type *> (info.type); + + if (!rtc) + return false; // Should never occur. + + assigned_params |= rtc->union_parameters ( + tc_union->name(), + tc_union->discriminator_type(), + tc_union->cases(), // Will be copied. + tc_union->member_count(), + tc_union->default_index()); + } + } + break; + case CORBA::tk_value: + case CORBA::tk_event: + { + // Set remaining parameters. + typedef ACE_Array_Base<TAO::TypeCode::Value_Field<CORBA::String_var, + CORBA::TypeCode_var> > + member_array_type; + + typedef TAO::TypeCode::Value<CORBA::String_var, + CORBA::TypeCode_var, + member_array_type, + TAO::True_RefCount_Policy> + typecode_type; + + typedef TAO::TypeCode::Recursive_Type<typecode_type, + CORBA::TypeCode_var, + member_array_type> + recursive_typecode_type; + + typecode_type * const tc_value = dynamic_cast<typecode_type *>(tc); + for (size_t i = 0; i < len; ++i) + { + TAO::TypeCodeFactory::TC_Info & info = recursive_tc[i]; - return tc_demarshal (cdr, tc, infos); + recursive_typecode_type * const rtc = + dynamic_cast<recursive_typecode_type *> (info.type); + + if (!rtc) + return false; // Should never occur. + + assigned_params |= rtc->valuetype_parameters ( + tc_value->name(), + tc_value->type_modifier(), + tc_value->concrete_base(), + tc_value->fields(), // Will be copied. + tc_value->member_count()); + } + } + break; + default: + break; + } + } + } + cleanup_tc_info_list(direct_infos); + return true; } TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/tao/AnyTypeCode/TypeCode_CDR_Extraction.h b/TAO/tao/AnyTypeCode/TypeCode_CDR_Extraction.h index 0e6d6015c97..3d99e69751e 100644 --- a/TAO/tao/AnyTypeCode/TypeCode_CDR_Extraction.h +++ b/TAO/tao/AnyTypeCode/TypeCode_CDR_Extraction.h @@ -39,156 +39,194 @@ namespace TAO typedef bool (*factory) (CORBA::TCKind, TAO_InputCDR &, CORBA::TypeCode_ptr &, + TC_Info_List &, TC_Info_List &); bool tc_null_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos); + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos); bool tc_void_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos); + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos); bool tc_short_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos); + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos); bool tc_long_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos); + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos); bool tc_ushort_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos); + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos); bool tc_ulong_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos); + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos); bool tc_float_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos); + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos); bool tc_double_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos); + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos); bool tc_boolean_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos); + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos); bool tc_char_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos); + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos); bool tc_octet_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos); + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos); bool tc_any_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos); + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos); bool tc_TypeCode_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos); + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos); bool tc_Principal_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos); + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos); bool tc_objref_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos); + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos); bool tc_struct_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos); + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos); bool tc_union_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos); + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos); bool tc_enum_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos); + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos); bool tc_string_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos); + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos); bool tc_sequence_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos); + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos); bool tc_array_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos); + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos); bool tc_alias_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos); + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos); bool tc_except_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos); + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos); bool tc_longlong_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos); + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos); bool tc_ulonglong_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos); + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos); bool tc_longdouble_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos); + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos); bool tc_wchar_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos); + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos); bool tc_wstring_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos); + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos); bool tc_fixed_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos); + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos); bool tc_value_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos); + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos); bool tc_value_box_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos); + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos); bool tc_native_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos); + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos); bool tc_abstract_interface_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos); + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos); bool tc_local_interface_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos); + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos); bool tc_component_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos); + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos); bool tc_home_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos); + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos); bool tc_event_factory (CORBA::TCKind kind, TAO_InputCDR & cdr, CORBA::TypeCode_ptr & tc, - TC_Info_List & infos); + TC_Info_List & indirect_infos, + TC_Info_List & direct_infos); } // End namespace TypeCodeFactory } // End namespace TAO diff --git a/TAO/tao/AnyTypeCode/Union_TypeCode.cpp b/TAO/tao/AnyTypeCode/Union_TypeCode.cpp index 6e616e79366..27c7eb6a8d1 100644 --- a/TAO/tao/AnyTypeCode/Union_TypeCode.cpp +++ b/TAO/tao/AnyTypeCode/Union_TypeCode.cpp @@ -104,6 +104,19 @@ template <typename StringType, typename TypeCodeType, class CaseArrayType, class RefCountPolicy> +const CaseArrayType & +TAO::TypeCode::Union<StringType, + TypeCodeType, + CaseArrayType, + RefCountPolicy>::cases (void) const +{ + return cases_; +} + +template <typename StringType, + typename TypeCodeType, + class CaseArrayType, + class RefCountPolicy> CORBA::Boolean TAO::TypeCode::Union<StringType, TypeCodeType, diff --git a/TAO/tao/AnyTypeCode/Union_TypeCode.h b/TAO/tao/AnyTypeCode/Union_TypeCode.h index 9757c9f9d65..abc4fe801e4 100644 --- a/TAO/tao/AnyTypeCode/Union_TypeCode.h +++ b/TAO/tao/AnyTypeCode/Union_TypeCode.h @@ -82,6 +82,9 @@ namespace TAO virtual void tao_release (void); //@} + /// Accessor for cases_ + const CaseArrayType& cases(void) const; + protected: /** diff --git a/TAO/tao/AnyTypeCode/Value_TypeCode.cpp b/TAO/tao/AnyTypeCode/Value_TypeCode.cpp index dc6aa73d6f7..8155a50d06c 100644 --- a/TAO/tao/AnyTypeCode/Value_TypeCode.cpp +++ b/TAO/tao/AnyTypeCode/Value_TypeCode.cpp @@ -112,6 +112,32 @@ template <typename StringType, typename TypeCodeType, class FieldArrayType, class RefCountPolicy> +const TypeCodeType& +TAO::TypeCode::Value<StringType, + TypeCodeType, + FieldArrayType, + RefCountPolicy>::concrete_base (void) const +{ + return concrete_base_; +} + +template <typename StringType, + typename TypeCodeType, + class FieldArrayType, + class RefCountPolicy> +const FieldArrayType& +TAO::TypeCode::Value<StringType, + TypeCodeType, + FieldArrayType, + RefCountPolicy>::fields (void) const +{ + return fields_; +} + +template <typename StringType, + typename TypeCodeType, + class FieldArrayType, + class RefCountPolicy> CORBA::Boolean TAO::TypeCode::Value<StringType, TypeCodeType, diff --git a/TAO/tao/AnyTypeCode/Value_TypeCode.h b/TAO/tao/AnyTypeCode/Value_TypeCode.h index 8f386b2e731..34abe3b7ec4 100644 --- a/TAO/tao/AnyTypeCode/Value_TypeCode.h +++ b/TAO/tao/AnyTypeCode/Value_TypeCode.h @@ -83,6 +83,12 @@ namespace TAO virtual void tao_release (void); //@} + /// Accessor for concrete_base_ + const TypeCodeType& concrete_base(void) const; + + /// Accessor for fields_ + const FieldArrayType& fields() const; + protected: /** diff --git a/TAO/tao/CSD_Framework/CSD_Framework_Loader.cpp b/TAO/tao/CSD_Framework/CSD_Framework_Loader.cpp index 62f9d46786c..5f9e5e65791 100644 --- a/TAO/tao/CSD_Framework/CSD_Framework_Loader.cpp +++ b/TAO/tao/CSD_Framework/CSD_Framework_Loader.cpp @@ -4,10 +4,6 @@ #include "tao/CSD_Framework/CSD_Framework_Loader.h" #include "tao/CSD_Framework/CSD_Object_Adapter_Factory.h" #include "tao/CSD_Framework/CSD_Strategy_Repository.h" -#include "tao/CSD_Framework/CSD_ORBInitializer.h" -#include "tao/PI/DLL_Resident_ORB_Initializer.h" -#include "tao/ORBInitializer_Registry.h" -#include "tao/ORB_Core.h" TAO_BEGIN_VERSIONED_NAMESPACE_DECL @@ -24,13 +20,12 @@ TAO_CSD_Framework_Loader::~TAO_CSD_Framework_Loader (void) int TAO_CSD_Framework_Loader::static_init (void) { - ACE_Service_Config::process_directive - (ace_svc_desc_TAO_CSD_Object_Adapter_Factory); - - ACE_Service_Config::process_directive - (ace_svc_desc_TAO_CSD_Strategy_Repository); - - ACE_Service_Config::process_directive (ace_svc_desc_TAO_CSD_Framework_Loader); + ACE_Service_Config::process_directive ( + ace_svc_desc_TAO_CSD_Object_Adapter_Factory); + ACE_Service_Config::process_directive ( + ace_svc_desc_TAO_CSD_Strategy_Repository); + ACE_Service_Config::process_directive ( + ace_svc_desc_TAO_CSD_Framework_Loader); return 0; } @@ -46,50 +41,6 @@ TAO_CSD_Framework_Loader::init (int, ACE_TCHAR* []) this->initialized_ = true; - // Register the ORB initializer. - try - { - PortableInterceptor::ORBInitializer_ptr temp_orb_initializer = - PortableInterceptor::ORBInitializer::_nil (); - - /// Register the CSD ORBInitializer. - ACE_NEW_THROW_EX (temp_orb_initializer, - TAO_CSD_ORBInitializer, - CORBA::NO_MEMORY ( - CORBA::SystemException::_tao_minor_code ( - TAO::VMCID, - ENOMEM), - CORBA::COMPLETED_NO)); - - PortableInterceptor::ORBInitializer_var orb_initializer; - orb_initializer = temp_orb_initializer; - - PortableInterceptor::ORBInitializer_ptr temp_dll_initializer = - PortableInterceptor::ORBInitializer::_nil (); - - ACE_NEW_THROW_EX (temp_dll_initializer, - PortableInterceptor::DLL_Resident_ORB_Initializer( - orb_initializer.in (), - ACE_TEXT ("TAO_CSD_ThreadPool")), - CORBA::NO_MEMORY ( - CORBA::SystemException::_tao_minor_code ( - TAO::VMCID, - ENOMEM), - CORBA::COMPLETED_NO)); - - PortableInterceptor::ORBInitializer_var dll_initializer; - dll_initializer = temp_dll_initializer; - - PortableInterceptor::register_orb_initializer (dll_initializer.in ()); - } - catch (const ::CORBA::Exception& ex) - { - ex._tao_print_exception ( - "Unexpected exception caught while " - "initializing the CSD Framework"); - return 1; - } - return 0; } diff --git a/TAO/tao/CSD_Framework/CSD_ORBInitializer.h b/TAO/tao/CSD_Framework/CSD_ORBInitializer.h index 1b8570ca311..d82a8c5d8c6 100644 --- a/TAO/tao/CSD_Framework/CSD_ORBInitializer.h +++ b/TAO/tao/CSD_Framework/CSD_ORBInitializer.h @@ -36,7 +36,7 @@ TAO_BEGIN_VERSIONED_NAMESPACE_DECL -class TAO_CSD_ORBInitializer +class TAO_CSD_FW_Export TAO_CSD_ORBInitializer : public virtual PortableInterceptor::ORBInitializer , public virtual ::CORBA::LocalObject { diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Queue.cpp b/TAO/tao/CSD_ThreadPool/CSD_TP_Queue.cpp index 87edf4b4c13..49603a489a6 100644 --- a/TAO/tao/CSD_ThreadPool/CSD_TP_Queue.cpp +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Queue.cpp @@ -36,6 +36,7 @@ TAO::CSD::TP_Queue::put(TP_Request* request) this->tail_->next_ = request; this->tail_ = request; } + } diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Queue.h b/TAO/tao/CSD_ThreadPool/CSD_TP_Queue.h index 9912c0e613a..3cdfdbe942c 100644 --- a/TAO/tao/CSD_ThreadPool/CSD_TP_Queue.h +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Queue.h @@ -22,6 +22,7 @@ #endif /* ACE_LACKS_PRAGMA_ONCE */ #include "tao/Versioned_Namespace.h" +#include "tao/orbconf.h" TAO_BEGIN_VERSIONED_NAMESPACE_DECL @@ -77,7 +78,6 @@ namespace TAO /// visiting every request). void accept_visitor(TP_Queue_Visitor& visitor); - private: /// The request at the front of the queue. diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Strategy_Factory.cpp b/TAO/tao/CSD_ThreadPool/CSD_TP_Strategy_Factory.cpp index a1e7be7af59..df57ecaaac7 100644 --- a/TAO/tao/CSD_ThreadPool/CSD_TP_Strategy_Factory.cpp +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Strategy_Factory.cpp @@ -34,103 +34,90 @@ TAO::CSD::TP_Strategy_Factory::init (int argc, initialized = 1; TAO_CSD_Strategy_Repository *repo = - ACE_Dynamic_Service<TAO_CSD_Strategy_Repository>::instance ("TAO_CSD_Strategy_Repository"); - - if (repo != 0) - repo->init(0,0); + ACE_Dynamic_Service<TAO_CSD_Strategy_Repository>::instance + (ACE_TEXT ("TAO_CSD_Strategy_Repository")); + + if (repo == 0) + { + TAO_CSD_ThreadPool::init (); + repo = ACE_Dynamic_Service<TAO_CSD_Strategy_Repository>::instance + (ACE_TEXT ("TAO_CSD_Strategy_Repository")); + } + + if (repo == 0) + { + if (TAO_debug_level > 0) + { + ACE_DEBUG((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - TP_Strategy_Factory - ") + ACE_TEXT ("cannot initialize strategy repo\n"))); + } + return -1; + } + + repo->init(0,0); // Parse any service configurator parameters. for (int curarg = 0; curarg < argc; curarg++) - if (ACE_OS::strcasecmp (argv[curarg], - ACE_TEXT("-CSDtp")) == 0) - { - ACE_CString poa_name; - unsigned long num_threads = 1; - bool serialize_servants = true; - - curarg++; - if (curarg < argc) - { - // Parse the parameter - ACE_CString arg ((const char *)argv[curarg]); - ACE_CString::size_type pos = arg.find (':'); - - if (pos == ACE_CString::npos) - { - poa_name = arg; - } - else - { - poa_name = arg.substr (0, pos); - - ACE_CString arg_remainder = - arg.substr (pos + 1, arg.length () - pos); - - ACE_CString num_thread_str; - - pos = arg_remainder.find (':'); - - if (pos == ACE_CString::npos) - { - num_thread_str = arg_remainder; - } - else - { - num_thread_str = arg_remainder.substr (0, pos); - - ACE_CString off_str = - arg_remainder.substr (pos + 1, arg.length () - pos); - - // Case-insensitive string comparison. - if (ACE_OS::strcasecmp (off_str.c_str(), "OFF") == 0) - { - serialize_servants = false; - } - } - - num_threads = ACE_OS::strtoul (num_thread_str.c_str (), 0, 10); - - if (num_threads == 0) - { - // Minimum of 1 thread required. - num_threads = 1; - } - } - - // Create the ThreadPool strategy for each named poa. - TP_Strategy* strategy = 0; - ACE_NEW_RETURN (strategy, - TP_Strategy (num_threads, serialize_servants), - -1); - CSD_Framework::Strategy_var objref = strategy; - - TAO_CSD_Strategy_Repository *repo = - ACE_Dynamic_Service<TAO_CSD_Strategy_Repository>::instance - ("TAO_CSD_Strategy_Repository"); - - if (repo == 0) - { - TAO_CSD_ThreadPool::init (); - repo = ACE_Dynamic_Service<TAO_CSD_Strategy_Repository>::instance ( - "TAO_CSD_Strategy_Repository" - ); - } - - - repo->add_strategy (poa_name, strategy); - } - } - else - { - if (TAO_debug_level > 0) - { - ACE_ERROR ((LM_ERROR, - ACE_TEXT("CSD_ORB_Loader: Unknown option ") - ACE_TEXT("<%s>.\n"), - argv[curarg])); - } - } - + { + if (ACE_OS::strcasecmp (argv[curarg], + ACE_TEXT("-CSDtp")) == 0) + { + ACE_CString poa_name; + unsigned long num_threads = 1; + bool serialize_servants = true; + + curarg++; + if (curarg >= argc) + { + return -1; + } + + // Parse the parameter + ACE_TCHAR *sep = ACE_OS::strchr (argv[curarg],':'); + if (sep == 0) + { + poa_name = ACE_TEXT_ALWAYS_CHAR (argv[curarg]); + } + else + { + *sep = 0; + poa_name = ACE_TEXT_ALWAYS_CHAR (argv[curarg]); + num_threads = ACE_OS::strtol (sep + 1, &sep, 10); + if (*sep != 0 && *sep != ':') + { + return -1; + } + if (*sep == ':') + { + if (ACE_OS::strcasecmp (sep + 1, "OFF") == 0) + { + serialize_servants = false; + } + } + } + + // Create the ThreadPool strategy for each named poa. + TP_Strategy* strategy = 0; + ACE_NEW_RETURN (strategy, + TP_Strategy (num_threads, serialize_servants), + -1); + CSD_Framework::Strategy_var objref = strategy; + repo->add_strategy (poa_name, strategy); + + } + else + { + if (TAO_debug_level > 0) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT("CSD_ORB_Loader: Unknown option ") + ACE_TEXT("<%s>.\n"), + argv[curarg])); + } + return -1; + } + } return 0; } diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Task.cpp b/TAO/tao/CSD_ThreadPool/CSD_TP_Task.cpp index c96a65eccb6..80f1ac5f23a 100644 --- a/TAO/tao/CSD_ThreadPool/CSD_TP_Task.cpp +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Task.cpp @@ -45,11 +45,11 @@ TAO::CSD::TP_Task::add_request(TP_Request* request) int -TAO::CSD::TP_Task::open(void* num_threads_ptr) +TAO::CSD::TP_Task::open(void* args) { Thread_Counter num = 1; - Thread_Counter* tmp = static_cast<Thread_Counter*> (num_threads_ptr); + Thread_Counter* tmp = static_cast<Thread_Counter*> (args); if (tmp == 0) { @@ -78,7 +78,8 @@ TAO::CSD::TP_Task::open(void* num_threads_ptr) { ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT ("(%P|%t) TP_Task failed to open. ") - ACE_TEXT ("num_threads (%u) is too large. Max is %d.\n"), + ACE_TEXT ("num_threads (%u) is too large. ") + ACE_TEXT ("Max is %d.\n"), num, MAX_THREADPOOL_TASK_WORKER_THREADS), -1); } diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Task.h b/TAO/tao/CSD_ThreadPool/CSD_TP_Task.h index fea7b2ecc4e..ce5c4b705c6 100644 --- a/TAO/tao/CSD_ThreadPool/CSD_TP_Task.h +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Task.h @@ -89,7 +89,7 @@ namespace TAO bool add_request(TP_Request* request); /// Activate the worker threads - virtual int open(void* num_threads_ptr = 0); + virtual int open(void* args = 0); /// The "mainline" executed by each worker thread. virtual int svc(); diff --git a/TAO/tao/CSD_ThreadPool/CSD_ThreadPool.cpp b/TAO/tao/CSD_ThreadPool/CSD_ThreadPool.cpp index 6b83baebc12..120f88a3a73 100644 --- a/TAO/tao/CSD_ThreadPool/CSD_ThreadPool.cpp +++ b/TAO/tao/CSD_ThreadPool/CSD_ThreadPool.cpp @@ -6,6 +6,12 @@ #include "tao/debug.h" #include "ace/Dynamic_Service.h" +#include "tao/CSD_Framework/CSD_ORBInitializer.h" +#include "tao/PI/DLL_Resident_ORB_Initializer.h" +#include "tao/ORBInitializer_Registry.h" +#include "tao/ORB_Core.h" + + TAO_BEGIN_VERSIONED_NAMESPACE_DECL int @@ -17,7 +23,55 @@ TAO_CSD_ThreadPool::init (void) initialized = 1; TAO_CSD_Framework_Loader::static_init(); - return ACE_Service_Config::process_directive (ace_svc_desc_TAO_CSD_TP_Strategy_Factory); + + // Register the ORB initializer. + try + { + PortableInterceptor::ORBInitializer_ptr temp_orb_initializer = + PortableInterceptor::ORBInitializer::_nil (); + + /// Register the CSD ORBInitializer. + ACE_NEW_THROW_EX (temp_orb_initializer, + TAO_CSD_ORBInitializer, + CORBA::NO_MEMORY ( + CORBA::SystemException::_tao_minor_code ( + TAO::VMCID, + ENOMEM), + CORBA::COMPLETED_NO)); + + PortableInterceptor::ORBInitializer_var orb_initializer; + orb_initializer = temp_orb_initializer; + + PortableInterceptor::ORBInitializer_ptr temp_dll_initializer = + PortableInterceptor::ORBInitializer::_nil (); + + ACE_NEW_THROW_EX (temp_dll_initializer, + PortableInterceptor::DLL_Resident_ORB_Initializer( + orb_initializer.in (), + ACE_TEXT ("TAO_CSD_ThreadPool")), + CORBA::NO_MEMORY ( + CORBA::SystemException::_tao_minor_code ( + TAO::VMCID, + ENOMEM), + CORBA::COMPLETED_NO)); + + PortableInterceptor::ORBInitializer_var dll_initializer; + dll_initializer = temp_dll_initializer; + + PortableInterceptor::register_orb_initializer ( + dll_initializer.in ()); + } + catch (const ::CORBA::Exception& ex) + { + ex._tao_print_exception ( + "Unexpected exception caught while " + "initializing the CSD Framework"); + return 1; + } + + + return ACE_Service_Config::process_directive ( + ace_svc_desc_TAO_CSD_TP_Strategy_Factory); } TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/tao/CSD_ThreadPool/CSD_ThreadPool.h b/TAO/tao/CSD_ThreadPool/CSD_ThreadPool.h index 82a5f082ee4..8b22f1a1b2c 100644 --- a/TAO/tao/CSD_ThreadPool/CSD_ThreadPool.h +++ b/TAO/tao/CSD_ThreadPool/CSD_ThreadPool.h @@ -17,8 +17,6 @@ #include "tao/CSD_ThreadPool/CSD_TP_Export.h" #include "tao/Versioned_Namespace.h" -#include "ace/Service_Object.h" -#include "ace/Service_Config.h" #if !defined (ACE_LACKS_PRAGMA_ONCE) @@ -28,11 +26,13 @@ TAO_BEGIN_VERSIONED_NAMESPACE_DECL /** - * @class TP_Strategy_Factory + * @class TAO_CSD_ThreadPool * - * @brief An ACE_Service_Object capable of creating TP_Strategy objects. + * @brief the static initializer for the CSD Thread Pool library * - * TBD - Explain in more detail. + * The loader appears to be born of the CSD_TP_Factory, which is the + * real service object. This separation seems to be necesary to ensure + * the CSD_Framework gets loaded prior to initializing the TP Factory. * */ class TAO_CSD_TP_Export TAO_CSD_ThreadPool diff --git a/TAO/tao/Client_Strategy_Factory.h b/TAO/tao/Client_Strategy_Factory.h index ece676673ea..4ccdc1543f6 100644 --- a/TAO/tao/Client_Strategy_Factory.h +++ b/TAO/tao/Client_Strategy_Factory.h @@ -32,6 +32,11 @@ ACE_END_VERSIONED_NAMESPACE_DECL TAO_BEGIN_VERSIONED_NAMESPACE_DECL +namespace TAO +{ + struct Invocation_Retry_Params; +} + class TAO_Transport_Mux_Strategy; class TAO_Wait_Strategy; class TAO_Transport; @@ -84,6 +89,11 @@ public: * Only applicable to RW wait strategy */ virtual bool use_cleanup_options (void) const = 0; + + /// Return the parameters used to optionally retry invocation + /// after an exception occurs. + virtual const TAO::Invocation_Retry_Params &invocation_retry_params (void) const = 0; + }; TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/tao/DynamicInterface/DII_Invocation_Adapter.cpp b/TAO/tao/DynamicInterface/DII_Invocation_Adapter.cpp index e302ccaff0f..1385d2fb5e5 100644 --- a/TAO/tao/DynamicInterface/DII_Invocation_Adapter.cpp +++ b/TAO/tao/DynamicInterface/DII_Invocation_Adapter.cpp @@ -96,8 +96,11 @@ namespace TAO TAO_Operation_Details &op, CORBA::Object_var &effective_target, Profile_Transport_Resolver &r, - ACE_Time_Value *&max_wait_time) + ACE_Time_Value *&max_wait_time, + Invocation_Retry_State *retry_state) { + ACE_UNUSED_ARG (retry_state); + // Simple sanity check if (this->mode_ != TAO_DII_INVOCATION || this->type_ != TAO_TWOWAY_INVOCATION) @@ -216,8 +219,11 @@ namespace TAO TAO_Operation_Details &op, CORBA::Object_var &effective_target, Profile_Transport_Resolver &r, - ACE_Time_Value *&max_wait_time) + ACE_Time_Value *&max_wait_time, + Invocation_Retry_State *retry_state) { + ACE_UNUSED_ARG (retry_state); + // Simple sanity check if (this->mode_ != TAO_DII_DEFERRED_INVOCATION || this->type_ != TAO_TWOWAY_INVOCATION) @@ -288,7 +294,8 @@ namespace TAO TAO_Operation_Details &, CORBA::Object_var &, Profile_Transport_Resolver &, - ACE_Time_Value *&) + ACE_Time_Value *&, + Invocation_Retry_State *) { return TAO_INVOKE_FAILURE; } diff --git a/TAO/tao/DynamicInterface/DII_Invocation_Adapter.h b/TAO/tao/DynamicInterface/DII_Invocation_Adapter.h index 80b2c6f9274..a7586d5a71b 100644 --- a/TAO/tao/DynamicInterface/DII_Invocation_Adapter.h +++ b/TAO/tao/DynamicInterface/DII_Invocation_Adapter.h @@ -102,7 +102,8 @@ namespace TAO TAO_Operation_Details &op, CORBA::Object_var &effective_target, Profile_Transport_Resolver &r, - ACE_Time_Value *&max_wait_time); + ACE_Time_Value *&max_wait_time, + Invocation_Retry_State *retry_state = 0); virtual Invocation_Status invoke_collocated_i ( TAO_Stub *stub, @@ -154,7 +155,8 @@ namespace TAO TAO_Operation_Details &op, CORBA::Object_var &effective_target, Profile_Transport_Resolver &r, - ACE_Time_Value *&max_wait_time); + ACE_Time_Value *&max_wait_time, + Invocation_Retry_State *retry_state = 0); virtual Invocation_Status invoke_collocated_i ( TAO_Stub *stub, @@ -199,7 +201,8 @@ namespace TAO TAO_Operation_Details &op, CORBA::Object_var &effective_target, Profile_Transport_Resolver &r, - ACE_Time_Value *&max_wait_time); + ACE_Time_Value *&max_wait_time, + Invocation_Retry_State *retry_state = 0); }; #endif /* TAO_HAS_AMI */ diff --git a/TAO/tao/Dynamic_TP/DTP_Config.cpp b/TAO/tao/Dynamic_TP/DTP_Config.cpp new file mode 100644 index 00000000000..47768ce0b99 --- /dev/null +++ b/TAO/tao/Dynamic_TP/DTP_Config.cpp @@ -0,0 +1,327 @@ +// $Id$ + +#include "tao/Dynamic_TP/DTP_Config.h" + +#if defined (TAO_HAS_CORBA_MESSAGING) && TAO_HAS_CORBA_MESSAGING != 0 + +#include "tao/Dynamic_TP/DTP_ORBInitializer.h" + +#include "tao/debug.h" +#include "ace/Dynamic_Service.h" +#include "ace/OS_NS_strings.h" + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +TAO_DTP_Config_Registry_Installer::TAO_DTP_Config_Registry_Installer (void) +{ + ACE_Service_Config::process_directive (ace_svc_desc_TAO_DTP_Config_Registry); +} + + +TAO_DTP_Config_Registry::TAO_DTP_Config_Registry (void) +{ +} + +TAO_DTP_Config_Registry::~TAO_DTP_Config_Registry (void) +{ +} + +int +TAO_DTP_Config_Registry::init (int , ACE_TCHAR* [] ) +{ + return 0; +} + +bool +TAO_DTP_Config_Registry::find (const ACE_CString& name, + TAO_DTP_Definition &entry) +{ + return registry_.find (name, entry) == 0; +} + +int +TAO_DTP_Config_Registry::bind (const ACE_CString& name, + TAO_DTP_Definition &entry) +{ + return registry_.bind (name, entry); +} + +int +TAO_DTP_Config_Registry::rebind (const ACE_CString& name, + TAO_DTP_Definition &entry) +{ + return registry_.rebind (name, entry); +} + +//------------------------------------------------------------------------- + +TAO_DTP_Config::TAO_DTP_Config (void) +{ +} + +TAO_DTP_Config::~TAO_DTP_Config (void) +{ +} + +int +TAO_DTP_Config::init (int argc, ACE_TCHAR* argv[]) +{ + TAO_DTP_Definition entry; + + ACE_TCHAR *name = 0; + bool overwrite = false; + + int curarg = 0; + int r = 0; + + for (curarg = 0; curarg < argc; ++curarg) + { + long val = 0; + if ((r = this->parse_string (curarg, + argc, + argv, + ACE_TEXT("-DTPName"),name )) != 0) + { + if (r < 0) + { + return -1; + } + } + else if ((r = this->parse_bool (curarg, + argc, + argv, + ACE_TEXT("-DTPOverwrite"), + overwrite )) != 0) + { + if (r < 0) + { + return -1; + } + } + else if ((r = this->parse_long (curarg, + argc, + argv, + ACE_TEXT("-DTPMin"), + val )) != 0) + { + if (r < 0) + { + return -1; + } + entry.min_threads_ = val; + } + else if ((r = this->parse_long (curarg, + argc, + argv, + ACE_TEXT("-DTPInit"), + val )) != 0) + { + if (r < 0) + { + return -1; + } + entry.init_threads_ = val; + } + else if ((r = this->parse_long (curarg, + argc, + argv, + ACE_TEXT("-DTPMax"), + val )) != 0) + { + if (r < 0) + { + return -1; + } + entry.max_threads_ = val; + } + else if ((r = this->parse_long (curarg, + argc, + argv, + ACE_TEXT("-DTPStack"), + val )) != 0) + { + if (r < 0) + { + return -1; + } + entry.stack_size_ = val; + } + else if ((r = this->parse_long (curarg, + argc, + argv, + ACE_TEXT("-DTPTImeout"), + val )) != 0) + { + if (r < 0) + { + return -1; + } + entry.timeout_ = val; + } + else if ((r = this->parse_long (curarg, + argc, + argv, + ACE_TEXT("-DTPQueue"), + val )) != 0) + { + if (r < 0) + { + return -1; + } + entry.queue_depth_ = val; + } + else + { + if (TAO_debug_level > 0) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - DTP_Config - ") + ACE_TEXT ("Unrecognized argv[%d], %C\n"), + curarg, argv[curarg])); + } + return -1; + } + } + + if ((entry.max_threads_ != -1 && entry.max_threads_ < entry.init_threads_) || + (entry.min_threads_ > entry.init_threads_)) + { + if (TAO_debug_level > 0) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - DTP_Config - ") + ACE_TEXT ("thread count constraint ") + ACE_TEXT ("violated, min: %d <= init: %d <= max: ") + ACE_TEXT ("%d or max = -1\n"), + entry.min_threads_, + entry.init_threads_, + entry.max_threads_)); + } + return 0; + } + + ACE_CString name_str = name; + ACE_Service_Gestalt *current = ACE_Service_Config::current(); + TAO_DTP_Config_Registry* registry = + ACE_Dynamic_Service<TAO_DTP_Config_Registry>::instance + (current, "DTP_Config_Registry", true); + + if (registry == 0) + { + current->process_directive (ace_svc_desc_TAO_DTP_Config_Registry); + registry = ACE_Dynamic_Service<TAO_DTP_Config_Registry>::instance + (current, "DTP_Config_Registry", true); + if (registry == 0) + { + if (TAO_debug_level > 0) + { + ACE_DEBUG((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - DTP_Config - ") + ACE_TEXT ("cannot initialize registry\n"))); + } + return -1; + } + } + + if (!overwrite) + { + return registry->bind(name_str, entry); + } + else + { + return registry->rebind(name_str, entry); + } + return 0; +} + +int +TAO_DTP_Config::parse_long (int &curarg, + int argc, ACE_TCHAR *argv[], + const ACE_TCHAR *match, long &value) +{ + ACE_TCHAR *str; + int result = this->parse_string (curarg, argc, argv, match, str); + if (result < 1) + return result; + + ACE_TCHAR *err = 0; + value = ACE_OS::strtol (str, &err, 10); + if (err && *err != 0) + { + this->report_option_value_error (match, str); + return -1; + } + return 1; +} + +int +TAO_DTP_Config::parse_bool (int &curarg, + int argc, ACE_TCHAR *argv[], + const ACE_TCHAR *match, bool &value) +{ + long num; + int result = this->parse_long (curarg, argc, argv, match, num); + if (result < 1) + return result; + + value = num != 0; + + return 1; +} + +int +TAO_DTP_Config::parse_string (int &curarg, + int argc, ACE_TCHAR *argv[], + const ACE_TCHAR *match, ACE_TCHAR *&value) +{ + if (ACE_OS::strcasecmp (argv[curarg], match) != 0) + return 0; + + ++curarg; + if (curarg >= argc) + { + this->report_option_value_error (match, ACE_TEXT("<missing>")); + return -1; + } + + value = argv[curarg]; + return 1; +} + + +void +TAO_DTP_Config::report_option_value_error (const ACE_TCHAR* option_name, + const ACE_TCHAR* option_value) +{ + if (TAO_debug_level > 0) + { + ACE_DEBUG((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - DTP_Config - unknown ") + ACE_TEXT ("argument <%s> for <%s>\n"), + option_value, option_name)); + } +} + + +///////////////////////////////////////////////////////////////////// + +ACE_FACTORY_DEFINE (TAO_Dynamic_TP, TAO_DTP_Config_Registry) +ACE_STATIC_SVC_DEFINE (TAO_DTP_Config_Registry, + ACE_TEXT ("DTP_Config_Registry"), + ACE_SVC_OBJ_T, + &ACE_SVC_NAME (TAO_DTP_Config_Registry), + ACE_Service_Type::DELETE_THIS + | ACE_Service_Type::DELETE_OBJ, + 0) +ACE_FACTORY_DEFINE (TAO_Dynamic_TP, TAO_DTP_Config) +ACE_STATIC_SVC_DEFINE (TAO_DTP_Config, + ACE_TEXT ("DTP_Config"), + ACE_SVC_OBJ_T, + &ACE_SVC_NAME (TAO_DTP_Config), + ACE_Service_Type::DELETE_THIS + | ACE_Service_Type::DELETE_OBJ, + 0) +TAO_END_VERSIONED_NAMESPACE_DECL + +#endif /* (TAO_HAS_CORBA_MESSAGING) && TAO_HAS_CORBA_MESSAGING != 0 */ + diff --git a/TAO/tao/Dynamic_TP/DTP_Config.h b/TAO/tao/Dynamic_TP/DTP_Config.h new file mode 100644 index 00000000000..6deddf381de --- /dev/null +++ b/TAO/tao/Dynamic_TP/DTP_Config.h @@ -0,0 +1,124 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file + * + * $Id$ + * + * Header file for Loading DynamicTP Configurations. + * + * + * @author + */ +//============================================================================= + +#ifndef TAO_DYNAMIC_TP_CONFIG_H +#define TAO_DYNAMIC_TP_CONFIG_H +#include /**/ "ace/pre.h" + +#include "tao/orbconf.h" + +#if defined (TAO_HAS_CORBA_MESSAGING) && TAO_HAS_CORBA_MESSAGING != 0 + +#include "tao/Dynamic_TP/dynamic_tp_export.h" +#include "ace/Service_Object.h" +#include "ace/Service_Config.h" +#include "ace/RB_Tree.h" +#include "ace/Synch.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +struct TAO_Dynamic_TP_Export TAO_DTP_Definition +{ + int min_threads_; // a default of -1 implies Lifespan of INFINITE, > 0 implies IDLE + int init_threads_; // default to 5 + int max_threads_; // a default of -1 implies no limit. + size_t stack_size_; + ACE_Time_Value timeout_; // default to 60 seconds + int queue_depth_; + + // Create explicit constructor to eliminate issues with non-initialized struct values. + TAO_DTP_Definition() : + min_threads_(-1), + init_threads_(5), + max_threads_(-1), + stack_size_(ACE_DEFAULT_THREAD_STACKSIZE), + timeout_(60,0), + queue_depth_(0){} + +}; + +class TAO_Dynamic_TP_Export TAO_DTP_Config_Registry_Installer +{ + public: + TAO_DTP_Config_Registry_Installer (void); +}; + +class TAO_Dynamic_TP_Export TAO_DTP_Config_Registry : public ACE_Service_Object +{ +public: + TAO_DTP_Config_Registry (void); + virtual ~TAO_DTP_Config_Registry (void); + + virtual int init (int argc, ACE_TCHAR* []); + + /// initializes the supplied set value with the configuration associated with the name, or returns false. + bool find (const ACE_CString& name, TAO_DTP_Definition &entry); + + int bind (const ACE_CString& name, TAO_DTP_Definition &entry); + int rebind (const ACE_CString& name, TAO_DTP_Definition &entry); + + private: + typedef ACE_RB_Tree<ACE_CString, TAO_DTP_Definition, ACE_Less_Than<ACE_CString>, ACE_Null_Mutex> Registry; + Registry registry_; +}; + +class TAO_Dynamic_TP_Export TAO_DTP_Config : public ACE_Service_Object +{ +public: + /// Constructor. + TAO_DTP_Config (void); + + /// Destructor. + virtual ~TAO_DTP_Config (void); + + /// Read a definition parameter set from the supplied args. + /// There must be a -TPName argument, which, if replicated will cause the set to be ignored, unless -TPOverwrite is also set + /// constriants: min threads <= initial threads <= max_threads. + /// defaults: min threads = initial = max = 5 + /// default lifespan = infinite + /// idle timeout is in secondes, default = 60 + /// default stack size = 0, system defined default used. + /// queue depth is in number of messages, default is infinite + /// Init can be called multiple times, + virtual int init (int argc, ACE_TCHAR* []); + +private: + int parse_long (int &curarg, int argc, ACE_TCHAR* argv[], const ACE_TCHAR *match, long &value); + int parse_bool (int &curarg, int argc, ACE_TCHAR* argv[], const ACE_TCHAR *match, bool &value); + int parse_string (int &curarg, int argc, ACE_TCHAR* argv[], const ACE_TCHAR *match, ACE_TCHAR *&value); + void report_option_value_error (const ACE_TCHAR* option_name, + const ACE_TCHAR* option_value); + +}; + +static TAO_DTP_Config_Registry_Installer config_installer; + + +ACE_STATIC_SVC_DECLARE_EXPORT (TAO_Dynamic_TP, TAO_DTP_Config_Registry) +ACE_FACTORY_DECLARE (TAO_Dynamic_TP, TAO_DTP_Config_Registry) + +ACE_STATIC_SVC_DECLARE_EXPORT (TAO_Dynamic_TP, TAO_DTP_Config) +ACE_FACTORY_DECLARE (TAO_Dynamic_TP, TAO_DTP_Config) + +TAO_END_VERSIONED_NAMESPACE_DECL + +#endif /* (TAO_HAS_CORBA_MESSAGING) && TAO_HAS_CORBA_MESSAGING != 0 */ + +#include /**/ "ace/post.h" +#endif /* TAO_DYNAMIC_TP_CONFIG_H */ diff --git a/TAO/tao/Dynamic_TP/DTP_ORBInitializer.cpp b/TAO/tao/Dynamic_TP/DTP_ORBInitializer.cpp new file mode 100644 index 00000000000..d193c3b54ea --- /dev/null +++ b/TAO/tao/Dynamic_TP/DTP_ORBInitializer.cpp @@ -0,0 +1,132 @@ +// $Id$ + +#include "tao/Dynamic_TP/DTP_ORBInitializer.h" + +#if defined (TAO_HAS_CORBA_MESSAGING) && TAO_HAS_CORBA_MESSAGING != 0 + +#include "tao/Dynamic_TP/DTP_Config.h" +#include "tao/Dynamic_TP/DTP_Thread_Lane_Resources_Manager.h" +#include "tao/Dynamic_TP/DTP_Thread_Pool.h" +#include "tao/Exception.h" +#include "tao/ORB_Core.h" +#include "tao/PI/ORBInitInfo.h" +#include "tao/debug.h" + +#include "ace/Service_Repository.h" +#include "ace/Svc_Conf.h" +#include "ace/Sched_Params.h" + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +TAO_DTP_ORBInitializer::TAO_DTP_ORBInitializer (/*const ACE_CString &tplist*/) +{ + +} + +void +TAO_DTP_ORBInitializer::pre_init (PortableInterceptor::ORBInitInfo_ptr info) +{ + TAO_ORBInitInfo_var tao_info = TAO_ORBInitInfo::_narrow (info); + + if (CORBA::is_nil (tao_info.in ())) + { + if (TAO_debug_level > 0) + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("(%P|%t) TAO_DTP_ORBInitializer::pre_init:\n") + ACE_TEXT ("(%P|%t) Unable to narrow ") + ACE_TEXT ("\"PortableInterceptor::ORBInitInfo_ptr\" to\n") + ACE_TEXT ("(%P|%t) \"TAO_ORBInitInfo *.\"\n"))); + + throw ::CORBA::INTERNAL (); + } + + + ACE_Service_Gestalt *gestalt = tao_info->orb_core ()->configuration(); + + ACE_Service_Object * const config_obj = + ACE_Dynamic_Service<ACE_Service_Object>::instance ( + gestalt, + "DTP_Config", + true); + if (config_obj == 0) + { + // no config manager object loaded + return; + } + + TAO_DTP_Config *config_mgr = dynamic_cast<TAO_DTP_Config *>(config_obj); + if (config_mgr == 0) + { + if (TAO_debug_level > 0) + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("(%P|%t) TAO_DTP_ORBInitializer::pre_init:\n") + ACE_TEXT ("(%P|%t) Unable to resolve DTP_Config ") + ACE_TEXT ("object\n"))); + + throw ::CORBA::INTERNAL (); + } + + // Set the name of the thread lane resources manager to be + // DTP_Thread_Lane_Resources_Manager. + tao_info->orb_core ()->orb_params () + ->thread_lane_resources_manager_factory_name ( + "DTP_Thread_Lane_Resources_Manager_Factory"); + ACE_Service_Config::process_directive ( + ace_svc_desc_TAO_DTP_Thread_Lane_Resources_Manager_Factory); + +} + +void +TAO_DTP_ORBInitializer::post_init (PortableInterceptor::ORBInitInfo_ptr info) +{ + TAO_ORBInitInfo_var tao_info = TAO_ORBInitInfo::_narrow (info); + + TAO_Thread_Lane_Resources_Manager &tlrm = + tao_info->orb_core ()->thread_lane_resources_manager(); + + ACE_Service_Gestalt *gestalt = tao_info->orb_core ()->configuration(); + + const char *dtp_name = + tao_info->orb_core ()->orb_params ()->dynamic_thread_pool_config_name (); + + if (dtp_name != 0 && dtp_name[0] != 0) + { + if (TAO_debug_level > 0) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) TAO_DTP_ORBInitializer::post_init ") + ACE_TEXT ("using thread pool name %s\n"), dtp_name)); + } + + TAO_DTP_Config_Registry *config_registry = + dynamic_cast<TAO_DTP_Config_Registry *> + (ACE_Dynamic_Service<ACE_Service_Object>::instance + (gestalt, "DTP_Config_Registry", true)); + + TAO_DTP_Definition def; + + if (!config_registry->find(dtp_name, def)) + { + if (TAO_debug_level > 0) + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("(%P|%t) TAO_DTP_ORBInitializer::") + ACE_TEXT ("post_init:\n") + ACE_TEXT ("(%P|%t) Unable to resolve ") + ACE_TEXT ("DTP_Config object\n"))); + + throw ::CORBA::INTERNAL (); + } + + TAO_DTP_Thread_Lane_Resources_Manager &dtp_tlrm = + dynamic_cast<TAO_DTP_Thread_Lane_Resources_Manager &>(tlrm); + + dtp_tlrm.tp_manager().create_threadpool (def); + } + + +} + + +TAO_END_VERSIONED_NAMESPACE_DECL + +#endif /* TAO_HAS_CORBA_MESSAGING && TAO_HAS_CORBA_MESSAGING != 0 */ diff --git a/TAO/tao/Dynamic_TP/DTP_ORBInitializer.h b/TAO/tao/Dynamic_TP/DTP_ORBInitializer.h new file mode 100644 index 00000000000..770ac31b50d --- /dev/null +++ b/TAO/tao/Dynamic_TP/DTP_ORBInitializer.h @@ -0,0 +1,72 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file DTP_ORBInitializer.h + * + * $Id$ + * + * @author Ossama Othman <ossama@uci.edu> + */ +//============================================================================= + + +#ifndef TAO_DYNAMIC_TP_ORB_INITIALIZER_H +#define TAO_DYNAMIC_TP_ORB_INITIALIZER_H + +#include /**/ "ace/pre.h" + +#include "tao/orbconf.h" + +#if defined (TAO_HAS_CORBA_MESSAGING) && TAO_HAS_CORBA_MESSAGING != 0 + +#include "tao/Dynamic_TP/dynamic_tp_export.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "tao/PI/PI.h" +#include "tao/LocalObject.h" + +// This is to remove "inherits via dominance" warnings from MSVC. +// MSVC is being a little too paranoid. +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable:4250) +#endif /* _MSC_VER */ + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +/// Dynamic_TP ORB initializer. +class TAO_DTP_ORBInitializer + : public virtual PortableInterceptor::ORBInitializer + , public virtual ::CORBA::LocalObject +{ +public: + + TAO_DTP_ORBInitializer (void); + + virtual void pre_init (PortableInterceptor::ORBInitInfo_ptr info); + + virtual void post_init (PortableInterceptor::ORBInitInfo_ptr info); + +private: + + /// Register Dynamic_TP policy factories. + void register_policy_factories (PortableInterceptor::ORBInitInfo_ptr info); + +private: +}; + +TAO_END_VERSIONED_NAMESPACE_DECL + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif /* _MSC_VER */ + +#endif /* TAO_HAS_CORBA_MESSAGING && TAO_HAS_CORBA_MESSAGING != 0 */ + +#include /**/ "ace/post.h" + +#endif /* TAO_DYNAMIC_TP_ORB_INITIALIZER_H */ diff --git a/TAO/tao/Dynamic_TP/DTP_ORB_Loader.cpp b/TAO/tao/Dynamic_TP/DTP_ORB_Loader.cpp new file mode 100644 index 00000000000..838e0a7e3d1 --- /dev/null +++ b/TAO/tao/Dynamic_TP/DTP_ORB_Loader.cpp @@ -0,0 +1,113 @@ +// $Id$ + +#include "tao/Dynamic_TP/DTP_ORB_Loader.h" + +#if defined (TAO_HAS_CORBA_MESSAGING) && TAO_HAS_CORBA_MESSAGING != 0 + +#include "tao/Dynamic_TP/DTP_ORBInitializer.h" + +#include "tao/debug.h" +#include "tao/ORB_Constants.h" +#include "tao/ORBInitializer_Registry.h" +#include "tao/SystemException.h" +#include "ace/Dynamic_Service.h" +#include "ace/OS_NS_strings.h" +#include "ace/Arg_Shifter.h" + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +TAO_DTP_ORB_Loader::TAO_DTP_ORB_Loader (void) + : initialized_ (false) +{ +} + +TAO_DTP_ORB_Loader::~TAO_DTP_ORB_Loader (void) +{ +} + +int +TAO_DTP_ORB_Loader::init (int argc, ACE_TCHAR* argv[]) +{ + ACE_TRACE ("TAO_DTP_ORB_Loader::init"); + + // Only allow initialization once. + if (this->initialized_) + return 0; + this->initialized_ = true; + + int curarg = 0; + for (curarg = 0; curarg < argc; ++curarg) + { + if (ACE_OS::strcasecmp (argv[curarg], ACE_TEXT ("-DTPORB")) == 0) + { + ++curarg; + if (curarg >= argc) + { + if (TAO_debug_level > 0) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - DTP_ORB_Loader - ") + ACE_TEXT ("DTPORB argument missing value\n"))); + } + return -1; + } + } + else + { + if (TAO_debug_level > 0) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - DTP_ORB_Loader -") + ACE_TEXT (" Unrecognized argv[%d], %C\n"), + curarg, argv[curarg])); + } + return -1; + } + } + + // Register the ORB initializer. + try + { + PortableInterceptor::ORBInitializer_ptr temp_orb_initializer = + PortableInterceptor::ORBInitializer::_nil (); + + /// Register the DynamicTP ORBInitializer. + ACE_NEW_THROW_EX (temp_orb_initializer, + TAO_DTP_ORBInitializer (), + CORBA::NO_MEMORY ( + CORBA::SystemException::_tao_minor_code ( + TAO::VMCID, + ENOMEM), + CORBA::COMPLETED_NO)); + + PortableInterceptor::ORBInitializer_var orb_initializer; + orb_initializer = temp_orb_initializer; + + PortableInterceptor::register_orb_initializer (orb_initializer.in ()); + } + catch (const ::CORBA::Exception& ex) + { + ex._tao_print_exception ( + "Unexpected exception caught while " + "initializing the RTORB"); + return 1; + } + + return 0; +} + + +///////////////////////////////////////////////////////////////////// + +ACE_FACTORY_DEFINE (TAO_Dynamic_TP, TAO_DTP_ORB_Loader) +ACE_STATIC_SVC_DEFINE (TAO_DTP_ORB_Loader, + ACE_TEXT ("DTP_ORB_Loader"), + ACE_SVC_OBJ_T, + &ACE_SVC_NAME (TAO_DTP_ORB_Loader), + ACE_Service_Type::DELETE_THIS + | ACE_Service_Type::DELETE_OBJ, + 0) +TAO_END_VERSIONED_NAMESPACE_DECL + +#endif /* (TAO_HAS_CORBA_MESSAGING) && TAO_HAS_CORBA_MESSAGING != 0 */ + diff --git a/TAO/tao/Dynamic_TP/DTP_ORB_Loader.h b/TAO/tao/Dynamic_TP/DTP_ORB_Loader.h new file mode 100644 index 00000000000..ffef32befd2 --- /dev/null +++ b/TAO/tao/Dynamic_TP/DTP_ORB_Loader.h @@ -0,0 +1,63 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file DTP_ORB_Loader.h + * + * $Id$ + * + * Header file for Loading DynamicTP. + * + * + * @author Phil Mesnier <mesnier_p@ociweb.com> + */ +//============================================================================= + +#ifndef TAO_DYNAMIC_TP_ORB_LOADER_H +#define TAO_DYNAMIC_TP_ORB_LOADER_H +#include /**/ "ace/pre.h" + +#include "tao/orbconf.h" + +#if defined (TAO_HAS_CORBA_MESSAGING) && TAO_HAS_CORBA_MESSAGING != 0 + +#include "tao/Dynamic_TP/dynamic_tp_export.h" +#include "ace/Service_Object.h" +#include "ace/Service_Config.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +class TAO_ORB_Core; + +class TAO_Dynamic_TP_Export TAO_DTP_ORB_Loader : public ACE_Service_Object +{ +public: + + /// Constructor. + TAO_DTP_ORB_Loader (void); + + /// Destructor. + virtual ~TAO_DTP_ORB_Loader (void); + + /// Initialize the DynamicTP loader hooks. + virtual int init (int argc, ACE_TCHAR* []); + +private: + /// Set to true after init is called. + bool initialized_; +}; + + +ACE_STATIC_SVC_DECLARE_EXPORT (TAO_Dynamic_TP, TAO_DTP_ORB_Loader) +ACE_FACTORY_DECLARE (TAO_Dynamic_TP, TAO_DTP_ORB_Loader) + +TAO_END_VERSIONED_NAMESPACE_DECL + +#endif /* (TAO_HAS_CORBA_MESSAGING) && TAO_HAS_CORBA_MESSAGING != 0 */ + +#include /**/ "ace/post.h" +#endif /* TAO_DYNAMIC_TP_ORB_LOADER_H */ diff --git a/TAO/tao/Dynamic_TP/DTP_POA_Loader.cpp b/TAO/tao/Dynamic_TP/DTP_POA_Loader.cpp new file mode 100644 index 00000000000..b11349f98a4 --- /dev/null +++ b/TAO/tao/Dynamic_TP/DTP_POA_Loader.cpp @@ -0,0 +1,199 @@ +// $Id$ + +#include "tao/Dynamic_TP/DTP_POA_Loader.h" + +#if defined (TAO_HAS_CORBA_MESSAGING) && TAO_HAS_CORBA_MESSAGING != 0 + +#include "tao/debug.h" +#include "tao/CSD_Framework/CSD_Framework_Loader.h" +#include "tao/Dynamic_TP/DTP_Config.h" +#include "tao/Dynamic_TP/DTP_POA_Strategy.h" +#include "ace/OS_NS_strings.h" +#include "tao/CSD_Framework/CSD_ORBInitializer.h" +#include "tao/PI/DLL_Resident_ORB_Initializer.h" +#include "tao/ORBInitializer_Registry.h" +#include "tao/ORB_Core.h" + + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +TAO_DTP_POA_Loader::TAO_DTP_POA_Loader (void) +{ +} + +TAO_DTP_POA_Loader::~TAO_DTP_POA_Loader (void) +{ +} + +int +TAO_DTP_POA_Loader::init (int argc, ACE_TCHAR* argv[]) +{ + //TAO_debug_level = 5; + + ACE_TRACE ("TAO_DTP_POA_Loader::init"); + + // Only allow initialization once. + static bool initialized = false; + if (initialized) + return 0; + initialized = true; + + TAO_CSD_Strategy_Repository * repo = + ACE_Dynamic_Service<TAO_CSD_Strategy_Repository>::instance + ("TAO_CSD_Strategy_Repository"); + + + /* Now create a POA Configuration Map Registry to look up what + thread pool settings are associated with each POA + */ + + if (repo == 0) + { + ACE_Service_Config::process_directive( + ace_svc_desc_TAO_CSD_Strategy_Repository); + repo = ACE_Dynamic_Service<TAO_CSD_Strategy_Repository>::instance + ("TAO_CSD_Strategy_Repository"); + } + + if (repo == 0) + { + if (TAO_debug_level > 0) + { + ACE_DEBUG((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - DTP_POA_Loader - ") + ACE_TEXT ("cannot initialize strategy repo\n"))); + } + return -1; + } + + repo->init(0,0); + + for (int curarg = 0; curarg < argc; curarg++) + { + + if (TAO_debug_level > 0) + { + ACE_DEBUG((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - DTP_POA_Loader - ") + ACE_TEXT ("parsing args\n"))); + } + + if (ACE_OS::strcasecmp (argv[curarg], ACE_TEXT ("-DTPPOAConfigMap")) + == 0) + { + ++curarg; + if (curarg >= argc) + { + this->report_option_value_error (ACE_TEXT ("-DTPPOAConfigMap"), + ACE_TEXT("<missing>")); + return -1; + } + if ((this->load_poa_map (argv[curarg], repo)) < 0) + { + return -1; + } + } + else + { + + /* + If we get here then we have another map set to process and + add to the map registry. + */ + if (TAO_debug_level > 0) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("DTP_POA_Loader: Missing option\n") + ACE_TEXT ("Usage: -DTPPOAConfigMap <comma-separated ") + ACE_TEXT ("list of POAs>:<POA Config Name>\n") + ACE_TEXT ("<%s>.\n"), + argv[curarg])); + } + } + + } + + return 0; +} + + +int +TAO_DTP_POA_Loader::load_poa_map (ACE_TCHAR *map, + TAO_CSD_Strategy_Repository *repo) +{ + + ACE_CString poa_name; + ACE_CString config_name; + TAO_DTP_POA_Strategy * strategy_container = 0; + + ACE_TCHAR *sep = ACE_OS::strchr (map, ':'); + + if (sep == 0) + { + if (TAO_debug_level > 0) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("DTP_POA_Loader: Missing option\n") + ACE_TEXT ("Usage: -DTPPOAConfigMap <comma-separated ") + ACE_TEXT ("list of POAs>:<POA Config Name>\n<%s>.\n"), + map)); + } + return -1; + } + + config_name = ACE_TEXT_ALWAYS_CHAR (sep + 1); + *sep = 0; + + // Now that we have a config name and a null strategy + // implementation class we can allocate a new instance of a + // strategy configuration container. + + ACE_NEW_RETURN(strategy_container, + TAO_DTP_POA_Strategy(config_name, + false), -1); + + sep = ACE_OS::strchr (map, ','); + while (sep != 0) + { + *sep = 0; + poa_name = ACE_TEXT_ALWAYS_CHAR (map); + repo->add_strategy (poa_name, strategy_container); + map = sep + 1; + sep = ACE_OS::strchr (map, ','); + } + poa_name = ACE_TEXT_ALWAYS_CHAR (map); + repo->add_strategy(poa_name, strategy_container); + + return 0; +} + +void +TAO_DTP_POA_Loader::report_option_value_error (const ACE_TCHAR* name, + const ACE_TCHAR* value) +{ + if (TAO_debug_level > 0) + { + ACE_DEBUG((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - DTP_POA_Loader - unknown ") + ACE_TEXT ("argument <%s> for <%s>\n"), + value, name)); + } +} + + +///////////////////////////////////////////////////////////////////// + + +ACE_FACTORY_DEFINE (TAO_Dynamic_TP, TAO_DTP_POA_Loader) +ACE_STATIC_SVC_DEFINE (TAO_DTP_POA_Loader, + ACE_TEXT ("DTP_POA_Loader"), + ACE_SVC_OBJ_T, + &ACE_SVC_NAME (TAO_DTP_POA_Loader), + ACE_Service_Type::DELETE_THIS + | ACE_Service_Type::DELETE_OBJ, + 0) + +TAO_END_VERSIONED_NAMESPACE_DECL + + +#endif /* TAO_HAS_CORBA_MESSAGING && TAO_HAS_CORBA_MESSAGING != 0 */ diff --git a/TAO/tao/Dynamic_TP/DTP_POA_Loader.h b/TAO/tao/Dynamic_TP/DTP_POA_Loader.h new file mode 100644 index 00000000000..6af4993b46c --- /dev/null +++ b/TAO/tao/Dynamic_TP/DTP_POA_Loader.h @@ -0,0 +1,62 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file DTP_POA_Loader.h + * + * $Id$ + * + * Header file for Loading DynamicTP. + * + * + * @author Phil Mesnier <mesnier_p@ociweb.com> + */ +//============================================================================= + +#ifndef TAO_DYNAMIC_TP_POA_LOADER_H +#define TAO_DYNAMIC_TP_POA_LOADER_H +#include /**/ "ace/pre.h" +#include "tao/orbconf.h" +#include "tao/Dynamic_TP/dynamic_tp_export.h" +#include "tao/Dynamic_TP/DTP_Config.h" +#include "tao/CSD_Framework/CSD_Strategy_Repository.h" +#include "ace/Synch.h" +#include "ace/Service_Object.h" +#include "ace/Service_Config.h" +#include "ace/RB_Tree.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +class TAO_Dynamic_TP_Export TAO_DTP_POA_Loader : public ACE_Service_Object +{ +public: + + /// Constructor. + TAO_DTP_POA_Loader (void); + + /// Destructor. + virtual ~TAO_DTP_POA_Loader (void); + + /// Initialize the DynamicTP loader hooks. + virtual int init (int argc, ACE_TCHAR* []); + +private: + /// Set to true after init is called. + int load_poa_map (ACE_TCHAR *map_str, + TAO_CSD_Strategy_Repository * reg); + + void report_option_value_error (const ACE_TCHAR* option_name, + const ACE_TCHAR* option_value); +}; + +ACE_STATIC_SVC_DECLARE_EXPORT (TAO_Dynamic_TP, TAO_DTP_POA_Loader) +ACE_FACTORY_DECLARE (TAO_Dynamic_TP, TAO_DTP_POA_Loader) + +TAO_END_VERSIONED_NAMESPACE_DECL + +#include /**/ "ace/post.h" +#endif /* TAO_DYNAMIC_TP_POA_LOADER_H */ diff --git a/TAO/tao/Dynamic_TP/DTP_POA_Strategy.cpp b/TAO/tao/Dynamic_TP/DTP_POA_Strategy.cpp new file mode 100644 index 00000000000..e715319750b --- /dev/null +++ b/TAO/tao/Dynamic_TP/DTP_POA_Strategy.cpp @@ -0,0 +1,422 @@ +// $Id$ + +#include "tao/Dynamic_TP/DTP_POA_Strategy.h" +#include "tao/CSD_ThreadPool/CSD_TP_Remote_Request.h" +#include "tao/CSD_ThreadPool/CSD_TP_Collocated_Synch_Request.h" +#include "tao/CSD_ThreadPool/CSD_TP_Collocated_Asynch_Request.h" +#include "tao/CSD_ThreadPool/CSD_TP_Custom_Synch_Request.h" +#include "tao/CSD_ThreadPool/CSD_TP_Custom_Asynch_Request.h" +#include "tao/CSD_ThreadPool/CSD_TP_Collocated_Synch_With_Server_Request.h" +#include "tao/ORB_Core.h" + +#if defined (TAO_HAS_CORBA_MESSAGING) && TAO_HAS_CORBA_MESSAGING != 0 + + +#if !defined (__ACE_INLINE__) +#include "tao/Dynamic_TP/DTP_POA_Strategy.inl" +#endif /* ! __ACE_INLINE__ */ + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + + +TAO_DTP_POA_Strategy::~TAO_DTP_POA_Strategy() +{ +} + +TAO_DTP_POA_Strategy::CustomRequestOutcome +TAO_DTP_POA_Strategy::custom_synch_request( + TAO::CSD::TP_Custom_Request_Operation* op) +{ + + TAO::CSD::TP_Servant_State::HandleType servant_state = + this->get_servant_state(op->servant()); + + TAO::CSD::TP_Custom_Synch_Request *req_ptr; + ACE_NEW_RETURN (req_ptr, + TAO::CSD::TP_Custom_Synch_Request(op, servant_state.in ()), + REQUEST_REJECTED); + + TAO::CSD::TP_Custom_Synch_Request_Handle request = req_ptr; + + if (!this->dtp_task_.add_request (request.in ())) + { + // The request was rejected by the task. + return REQUEST_REJECTED; + } + + // Now we wait until the request is handled (executed or cancelled). + return (request->wait ()) ? REQUEST_EXECUTED : REQUEST_CANCELLED; +} + +TAO_DTP_POA_Strategy::CustomRequestOutcome +TAO_DTP_POA_Strategy::custom_asynch_request ( + TAO::CSD::TP_Custom_Request_Operation* op) +{ + + TAO::CSD::TP_Servant_State::HandleType servant_state = + this->get_servant_state (op->servant ()); + + TAO::CSD::TP_Custom_Asynch_Request *req_ptr; + ACE_NEW_RETURN (req_ptr, + TAO::CSD::TP_Custom_Asynch_Request (op, servant_state.in ()), + REQUEST_REJECTED); + + TAO::CSD::TP_Custom_Asynch_Request_Handle request = req_ptr; + + return (this->dtp_task_.add_request (request.in ())) + ? REQUEST_DISPATCHED : REQUEST_REJECTED; +} + +bool +TAO_DTP_POA_Strategy::poa_activated_event_i (TAO_ORB_Core& orb_core) +{ + + this->dtp_task_.thr_mgr (orb_core.thr_mgr ()); + + // Activates the worker threads, and waits until all have been started. + if (!this->config_initialized_) + { + TAO_DTP_Config_Registry * config_repo = + ACE_Dynamic_Service<TAO_DTP_Config_Registry>::instance + ("DTP_Config_Registry"); + + if (config_repo == 0) + { + if (TAO_debug_level > 0) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - DTP_POA_Strategy - ") + ACE_TEXT ("cannot retrieve configuration repo\n"))); + } + return false; + } + else + { + TAO_DTP_Definition config_entry; + if (!config_repo->find (this->dynamic_tp_config_name_, config_entry)) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - DTP_POA_Strategy - ") + ACE_TEXT ("warning: config not found...using ") + ACE_TEXT ("defaults!\n"))); + + } + this->set_dtp_config (config_entry); + //this->dtp_task_.set_init_pool_threads(config_entry.init_threads_); + //this->dtp_task_.set_min_pool_threads(config_entry.min_threads_); + //this->dtp_task_.set_max_pool_threads(config_entry.max_threads_); + //this->dtp_task_.set_thread_idle_time(config_entry.timeout_); + //this->dtp_task_.set_thread_stack_size(config_entry.stack_size_); + //this->dtp_task_.set_max_request_queue_depth(config_entry.queue_depth_); + } + + + + } + return (this->dtp_task_.open () == 0); + +} + +void +TAO_DTP_POA_Strategy::poa_deactivated_event_i () +{ + // Passing in a value of 1 means that we want to shutdown the task, which + // equates to causing all worker threads to shutdown. The worker threads + // themselves will also invoke the close() method, but the passed-in value + // will be 0. So, a 1 means "shutdown", and a 0 means "a single worker + // thread is going away". + this->dtp_task_.close(1); +} + +TAO::CSD::Strategy_Base::DispatchResult +TAO_DTP_POA_Strategy::dispatch_remote_request_i + (TAO_ServerRequest& server_request, + const PortableServer::ObjectId& object_id, + PortableServer::POA_ptr poa, + const char* operation, + PortableServer::Servant servant) +{ + TAO::CSD::TP_Servant_State::HandleType servant_state = + this->get_servant_state (servant); + + // Now we can create the TP_Remote_Request object, and then add it to our + // task_'s "request queue". + // + // TBD-CSD: Need to use a Cached Allocator to "create" the + // TP_Remote_Request objects. For now, use the heap. + TAO::CSD::TP_Remote_Request *req_ptr; + ACE_NEW_RETURN (req_ptr, + TAO::CSD::TP_Remote_Request (server_request, + object_id, + poa, + operation, + servant, + servant_state.in ()), + TAO::CSD::Strategy_Base::DISPATCH_REJECTED); + + TAO::CSD::TP_Remote_Request_Handle request = req_ptr; + + // Hand the request object to our task so that it can add the request + // to its "request queue". + if (!this->dtp_task_.add_request (request.in ())) + { + // Return the DISPATCH_REJECTED return code so that the caller (our + // base class' dispatch_request() method) knows that we did + // not handle the request, and that it should be rejected. + return TAO::CSD::Strategy_Base::DISPATCH_REJECTED; + } + + return TAO::CSD::Strategy_Base::DISPATCH_HANDLED; +} + +TAO::CSD::Strategy_Base::DispatchResult +TAO_DTP_POA_Strategy::dispatch_collocated_request_i + (TAO_ServerRequest& server_request, + const PortableServer::ObjectId& object_id, + PortableServer::POA_ptr poa, + const char* operation, + PortableServer::Servant servant) +{ + + + TAO::CSD::TP_Servant_State::HandleType servant_state = + this->get_servant_state (servant); + + bool is_sync_with_server = server_request.sync_with_server (); + bool is_synchronous = server_request.response_expected (); + + TAO::CSD::TP_Collocated_Synch_Request_Handle + synch_request; + TAO::CSD::TP_Collocated_Synch_With_Server_Request_Handle + synch_with_server_request; + TAO::CSD::TP_Request_Handle + request; + + // Create the request object using the appropriate concrete type. + if (is_sync_with_server) + { + TAO::CSD::TP_Collocated_Synch_With_Server_Request *req_ptr; + ACE_NEW_RETURN (req_ptr, + TAO::CSD::TP_Collocated_Synch_With_Server_Request + (server_request, + object_id, + poa, + operation, + servant, + servant_state.in ()), + DISPATCH_REJECTED); + + synch_with_server_request = req_ptr; + + // Give the request handle its own "copy". + synch_with_server_request->_add_ref (); + request = synch_with_server_request.in (); + } + else if (is_synchronous) + { + + TAO::CSD::TP_Collocated_Synch_Request *req_ptr; + ACE_NEW_RETURN (req_ptr, + TAO::CSD::TP_Collocated_Synch_Request ( + server_request, + object_id, + poa, + operation, + servant, + servant_state.in ()), + DISPATCH_REJECTED); + + synch_request = req_ptr; + + // Give the request handle its own "copy". + synch_request->_add_ref (); + request = synch_request.in (); + } + else + { + TAO::CSD::TP_Collocated_Asynch_Request *req_ptr; + ACE_NEW_RETURN (req_ptr, + TAO::CSD::TP_Collocated_Asynch_Request (server_request, + object_id, + poa, + operation, + servant, + servant_state.in ()), + DISPATCH_REJECTED); + + // Just use the (base) request handle to hold the request object. + request = req_ptr; + } + + // Hand the request object to our task so that it can add the request + // to its "request queue". + if (!this->dtp_task_.add_request (request.in ())) + { + // Return the DISPATCH_REJECTED return code so that the caller (our + // base class' dispatch_request() method) knows that we did + // not handle the request, and that it should be rejected. + return DISPATCH_REJECTED; + } + + // We need to wait on the request object if the request type is a + // synchronous request. + if (!synch_request.is_nil ()) + { + int srw = synch_request->wait (); + if (srw == false) + { + // Raise exception when request was cancelled. + throw ::CORBA::NO_IMPLEMENT (); + } + } + else if (!synch_with_server_request.is_nil()) + { + bool swsr = synch_with_server_request->wait(); + if (swsr == false) + { + // Raise exception when request was cancelled. + throw ::CORBA::NO_IMPLEMENT (); + } + } + + return DISPATCH_HANDLED; +} + +void +TAO_DTP_POA_Strategy::servant_activated_event_i + (PortableServer::Servant servant, + const PortableServer::ObjectId&) +{ + if (this->serialize_servants_) + { + // Add the servant to the servant state map. + this->servant_state_map_.insert (servant); + } +} + +void +TAO_DTP_POA_Strategy::servant_deactivated_event_i + (PortableServer::Servant servant, + const PortableServer::ObjectId&) +{ + // Cancel all requests stuck in the queue for the specified servant. + this->dtp_task_.cancel_servant (servant); + + if (this->serialize_servants_) + { + // Remove the servant from the servant state map. + this->servant_state_map_.remove (servant); + } +} + +void +TAO_DTP_POA_Strategy::cancel_requests (PortableServer::Servant servant) +{ + // Cancel all requests stuck in the queue for the specified servant. + this->dtp_task_.cancel_servant (servant); +} + +TAO::CSD::TP_Servant_State::HandleType +TAO_DTP_POA_Strategy::get_servant_state (PortableServer::Servant servant) +{ + TAO::CSD::TP_Servant_State::HandleType servant_state; + + if (this->serialize_servants_) + { + servant_state = this->servant_state_map_.find (servant); + } + + return servant_state; +} + +void +TAO_DTP_POA_Strategy::set_dtp_config (TAO_DTP_Definition &tp_config) +{ + + if (tp_config.min_threads_ <= 0) + { + this->dtp_task_.set_min_pool_threads (1); + this->dtp_task_.set_thread_idle_time (ACE_Time_Value (0,0)); + } + else + { + this->dtp_task_.set_min_pool_threads (tp_config.min_threads_); + this->dtp_task_.set_thread_idle_time (tp_config.timeout_); + } + + // initial_pool_threads_ + if ((tp_config.init_threads_ <= 0) || + (tp_config.init_threads_ < tp_config.min_threads_)) + { + this->dtp_task_.set_init_pool_threads (this->dtp_task_.get_min_pool_threads()); + } + else + { + this->dtp_task_.set_init_pool_threads (tp_config.init_threads_); + } + + // max_pool_threads_ + + if (tp_config.max_threads_ <= 0) + { + // Set to 0 so that max is unbounded. + this->dtp_task_.set_max_pool_threads(0); + } + else + if (tp_config.max_threads_ < tp_config.init_threads_) + { + this->dtp_task_.set_max_pool_threads( + this->dtp_task_.get_init_pool_threads ()); + } + else + { + this->dtp_task_.set_max_pool_threads (tp_config.max_threads_); + } + + // thread_stack_size_ + + if (tp_config.stack_size_ <= 0) + { + this->dtp_task_.set_thread_stack_size (ACE_DEFAULT_THREAD_STACKSIZE); + } + else + { + this->dtp_task_.set_thread_stack_size (tp_config.stack_size_); + } + + // max_request_queue_depth_ + if (tp_config.queue_depth_ < 0) + { + this->dtp_task_.set_max_request_queue_depth (0); + } + else + { + this->dtp_task_.set_max_request_queue_depth (tp_config.queue_depth_); + } + + + if (TAO_debug_level > 4) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - DTP_POA_Strategy: ") + ACE_TEXT ("Initialized with:\n") + ACE_TEXT ("TAO (%P|%t) - DTP_POA_Strategy initial_pool_threads_=") + ACE_TEXT ("[%d]\n") + ACE_TEXT ("TAO (%P|%t) - DTP_POA_Strategy min_pool_threads_=[%d]\n") + ACE_TEXT ("TAO (%P|%t) - DTP_POA_Strategy max_pool_threads_=[%d]\n") + ACE_TEXT ("TAO (%P|%t) - DTP_POA_Strategy max_request_queue_depth_=") + ACE_TEXT ("[%d]\n") + ACE_TEXT ("TAO (%P|%t) - DTP_POA_Strategy thread_stack_size_=[%d]\n") + ACE_TEXT ("TAO (%P|%t) - DTP_POA_Strategy thread_idle_time_=[%d]\n"), + this->dtp_task_.get_init_pool_threads(), + this->dtp_task_.get_min_pool_threads(), + this->dtp_task_.get_max_pool_threads(), + this->dtp_task_.get_max_request_queue_depth(), + this->dtp_task_.get_thread_stack_size(), + this->dtp_task_.get_thread_idle_time())); + } +} +TAO_END_VERSIONED_NAMESPACE_DECL + + +#endif /* TAO_HAS_CORBA_MESSAGING && TAO_HAS_CORBA_MESSAGING != 0 */ diff --git a/TAO/tao/Dynamic_TP/DTP_POA_Strategy.h b/TAO/tao/Dynamic_TP/DTP_POA_Strategy.h new file mode 100644 index 00000000000..51533e334b1 --- /dev/null +++ b/TAO/tao/Dynamic_TP/DTP_POA_Strategy.h @@ -0,0 +1,220 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file DTP_POA_Strategy.h + * + * $Id$ + * + * @author Marc Neeley <neeleym@ociweb.com> + */ +//============================================================================= + +#ifndef TAO_DYNAMIC_TP_POA_STRATEGY_H +#define TAO_DYNAMIC_TP_POA_STRATEGY_H + +#include /**/ "ace/pre.h" +#include "tao/Dynamic_TP/dynamic_tp_export.h" +#include "tao/Dynamic_TP/DTP_Config.h" +#include "tao/Dynamic_TP/DTP_Task.h" +#include "tao/CSD_ThreadPool/CSD_TP_Servant_State_Map.h" +#include "tao/CSD_ThreadPool/CSD_TP_Custom_Request_Operation.h" +#include "tao/CSD_ThreadPool/CSD_TP_Strategy.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "tao/CSD_Framework/CSD_Strategy_Base.h" +#include "tao/Intrusive_Ref_Count_Handle_T.h" +#include "ace/OS_NS_strings.h" + + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + + +class TAO_DTP_POA_Strategy; +typedef TAO_Intrusive_Ref_Count_Handle<TAO_DTP_POA_Strategy> + TAO_DTP_POA_Strategy_Handle; + +namespace TAO +{ + namespace CSD + { + class TP_Custom_Request_Operation; + } +} + + +/** + * @class TAO_DTP_POA_Strategy + * + * @brief + * + */ +class TAO_Dynamic_TP_Export TAO_DTP_POA_Strategy: + public TAO::CSD::Strategy_Base +{ + public: + + /// Constructors. + /// This constructor supports situations where dynamic instantiation + /// of a thread pool for POAs is initiated from a svc.conf file. + /// A configuration name is passed in such that the object can + /// lookup a configuration in a pre-populated repository. + TAO_DTP_POA_Strategy(ACE_CString tp_config_name, + bool serialize_servants = true); + + /// This constructor supports situations where explicit instantiation + /// of a thread pool for POAs is initiated from an application, such as + /// the use of the apply_to() method. + TAO_DTP_POA_Strategy(TAO_DTP_Definition * tp_config, + bool serialize_servants = true); + + /// Virtual Destructor. + virtual ~TAO_DTP_POA_Strategy(); + + /// Turn on/off serialization of servants. + void set_servant_serialization(bool serialize_servants); + + /// Return codes for the custom dispatch_request() methods. + enum CustomRequestOutcome + { + /// The request was successfully put on the request queue. + REQUEST_DISPATCHED, + /// The request has been executed/completed by a worker thread. + REQUEST_EXECUTED, + /// The request was removed from the queue and cancelled. + REQUEST_CANCELLED, + /// The request queue rejected the request + REQUEST_REJECTED + }; + + /// Inject a synchronous, custom request into the request queue. + /// This will block the calling thread until the request is handled + /// (dispatched or cancelled) or rejected. + /// Will return REQUEST_EXECUTED, REQUEST_CANCELLED, or REQUEST_REJECTED. + CustomRequestOutcome custom_synch_request + (TAO::CSD::TP_Custom_Request_Operation* op); + + /// Inject an asynchronous, custom request into the request queue. + /// This will return control to the calling thread once the request + /// has been placed into the queue (or rejected). + /// Will return REQUEST_DISPATCHED or REQUEST_REJECTED. + CustomRequestOutcome custom_asynch_request + (TAO::CSD::TP_Custom_Request_Operation* op); + + /// Cancel all requests that are targeted for the provided servant. + /// This is requested on the user application level. + void cancel_requests(PortableServer::Servant servant); + + + protected: + + /// Handle the dispatching of a remote request. + /// + /// This will cause a new "request" object to be created and pushed + /// on to a "request queue". The worker threads are responsible for + /// servicing the queue, and performing the actual dispatch logic. + virtual Strategy_Base::DispatchResult dispatch_remote_request_i + (TAO_ServerRequest& server_request, + const PortableServer::ObjectId& object_id, + PortableServer::POA_ptr poa, + const char* operation, + PortableServer::Servant servant); + + /// Handle the dispatching of a collocated request. + /// + /// This will cause a new "request" object to be created and pushed + /// on to a "request queue". The worker threads are responsible for + /// servicing the queue, and performing the actual dispatch logic. + virtual Strategy_Base::DispatchResult dispatch_collocated_request_i + (TAO_ServerRequest& server_request, + const PortableServer::ObjectId& object_id, + PortableServer::POA_ptr poa, + const char* operation, + PortableServer::Servant servant); + + /// Event - The POA has been activated. + /// This will activate the worker thread(s). + /// Returns true if the worker threads were activated successfully. + /// Otherwise, returns false. + virtual bool poa_activated_event_i(TAO_ORB_Core& orb_core); + + /// Event - The POA has been deactivated. + /// This will shutdown the worker thread(s). + virtual void poa_deactivated_event_i(); + + /// Event - A servant has been activated + virtual void servant_activated_event_i + (PortableServer::Servant servant, + const PortableServer::ObjectId& oid); + + /// Event - A servant has been deactivated + virtual void servant_deactivated_event_i + (PortableServer::Servant servant, + const PortableServer::ObjectId& oid); + + private: + + + /** + * Helper method that is responsible for looking up the servant + * state object in the servant state map *if* the "serialize + * servants" flag is set to true. In the case where the + * "serialize servants" flag is set to false, then a "nil" + * servant state handle object is returned. + * + * @param servant - input - a pointer to the servant object. + * + * @returns a handle to a servant state object. + * + * @throw PortableServer::POA::ServantNotActive if the servant + * state cannot be determined. + */ + TAO::CSD::TP_Servant_State::HandleType get_servant_state + (PortableServer::Servant servant); + + /// The "serialize servants" flag. + bool serialize_servants_; + + /// The map of servant state objects - only used when the + /// "serialize servants" flag is set to true. + TAO::CSD::TP_Servant_State_Map servant_state_map_; + + /// This holds the name of a configuration that have been loaded + /// into a DTP_Config_Registry. This is the key to the RB + /// Tree entry. + + ACE_CString dynamic_tp_config_name_; + + /// This is the active object used by the worker threads. + /// The request queue is owned/managed by the task object. + /// The strategy object puts requests into the task's request + /// queue, and the worker threads service the queued requests + /// by performing the actual servant request dispatching logic. + TAO_DTP_Task dtp_task_; + + + /// This boolean is used to determine if the configuration has + /// been sent in from an application or, if false, needs to be + /// looked up from a Dynamic TP Config repo. It works in conjunction with + /// dynamic_tp_config_name_ above. + + bool config_initialized_; + + + void set_dtp_config(TAO_DTP_Definition &tp_config); +}; + + + +TAO_END_VERSIONED_NAMESPACE_DECL + +#if defined (__ACE_INLINE__) +#include "tao/Dynamic_TP/DTP_POA_Strategy.inl" +#endif /* __ACE_INLINE__ */ + +#include /**/ "ace/post.h" + +#endif /* TAO_DYNAMIC_TP_POA_STRATEGY_H */ diff --git a/TAO/tao/Dynamic_TP/DTP_POA_Strategy.inl b/TAO/tao/Dynamic_TP/DTP_POA_Strategy.inl new file mode 100644 index 00000000000..3ce52bb554b --- /dev/null +++ b/TAO/tao/Dynamic_TP/DTP_POA_Strategy.inl @@ -0,0 +1,35 @@ +// -*- C++ -*- +// +// $Id$ + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +ACE_INLINE +/// Constructor. +TAO_DTP_POA_Strategy::TAO_DTP_POA_Strategy (ACE_CString tp_config_name, + bool ss) + : serialize_servants_ (ss), + config_initialized_ (false) +{ + this->dynamic_tp_config_name_ = tp_config_name; +} + +ACE_INLINE +TAO_DTP_POA_Strategy::TAO_DTP_POA_Strategy (TAO_DTP_Definition * tp_config, + bool ss) + : serialize_servants_ (ss), + config_initialized_ (true) +{ + this->set_dtp_config (*tp_config); +} + +ACE_INLINE +void +TAO_DTP_POA_Strategy::set_servant_serialization (bool serialize_servants) +{ + // Simple Mutator. + this->serialize_servants_ = serialize_servants; +} + + +TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/tao/Dynamic_TP/DTP_Task.cpp b/TAO/tao/Dynamic_TP/DTP_Task.cpp new file mode 100644 index 00000000000..cc6f30c310c --- /dev/null +++ b/TAO/tao/Dynamic_TP/DTP_Task.cpp @@ -0,0 +1,479 @@ +// $Id$ + +#include "tao/Dynamic_TP/DTP_Task.h" +#include "tao/CSD_ThreadPool/CSD_TP_Request.h" +#include "tao/CSD_ThreadPool/CSD_TP_Dispatchable_Visitor.h" +#include "tao/CSD_ThreadPool/CSD_TP_Cancel_Visitor.h" + +#if !defined (__ACE_INLINE__) +# include "tao/Dynamic_TP/DTP_Task.inl" +#endif /* ! __ACE_INLINE__ */ + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +TAO_DTP_Task::TAO_DTP_Task () + : aw_lock_ (), + queue_lock_ (), + work_lock_ (), + work_available_ (this->work_lock_), + active_workers_ (this->aw_lock_), + accepting_requests_ (false), + shutdown_ (false), + opened_ (false), + num_queue_requests_ ((size_t)0) +{ +} + +TAO_DTP_Task::~TAO_DTP_Task() +{ +} + +bool +TAO_DTP_Task::add_request (TAO::CSD::TP_Request* request) +{ + { + ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, guard, this->queue_lock_, false); + ++this->num_queue_requests_; + if ((this->num_queue_requests_ > this->max_request_queue_depth_) && + (this->max_request_queue_depth_ != 0)) + { + this->accepting_requests_ = false; + } + + if (!this->accepting_requests_) + { + if (TAO_debug_level > 4) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - DTP_Task::add_request() ") + ACE_TEXT ("not accepting requests.\n") + ACE_TEXT ("TAO (%P|%t) - DTP_Task::add_request() ") + ACE_TEXT ("num_queue_requests_ : [%d]\n") + ACE_TEXT ("TAO (%P|%t) - DTP_Task::add_request() ") + ACE_TEXT ("max_request_queue_depth_ : [%d]\n"), + this->num_queue_requests_, + this->max_request_queue_depth_)); + } + --this->num_queue_requests_; + return false; + } + + // We have made the decision that the request is going to be placed upon + // the queue_. Inform the request that it is about to be placed into + // a request queue. Some requests may not need to do anything in + // preparation of being placed into a queue. Others, however, may need + // to perfom a "clone" operation on some underlying request data before + // the request can be properly placed into a queue. + request->prepare_for_queue(); + + this->queue_.put(request); + } + + { + ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, guard, this->work_lock_, false); + this->work_available_.signal (); + if (TAO_debug_level > 4 ) + { + ACE_DEBUG((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - DTP_Task::add_request() - ") + ACE_TEXT ("work available\n"))); + } + } + + return true; +} + +size_t +TAO_DTP_Task::get_init_pool_threads () +{ + return (this->init_pool_threads_); +} + +size_t +TAO_DTP_Task::get_min_pool_threads () +{ + return(this->min_pool_threads_); +} + +size_t TAO_DTP_Task::get_max_pool_threads () +{ + return(this->max_pool_threads_); +} + +size_t +TAO_DTP_Task::get_max_request_queue_depth () +{ + return(this->max_request_queue_depth_); +} + +size_t +TAO_DTP_Task::get_thread_stack_size () +{ + return(this->thread_stack_size_); +} + +time_t +TAO_DTP_Task::get_thread_idle_time () +{ + return(this->thread_idle_time_.sec()); +} + +int +TAO_DTP_Task::open (void* /* args */) +{ + size_t num = 1; + + // Open_Args* tmp = static_cast<Open_Args *> (args); + + //if (tmp == 0) + // { + // //FUZZ: disable check_for_lack_ACE_OS + // ACE_ERROR_RETURN ((LM_ERROR, + // ACE_TEXT ("(%P|%t) DTP_Task::open() failed to open. ") + // ACE_TEXT ("Invalid argument type passed to open().\n")), + // -1); + // //FUZZ: enable check_for_lack_ACE_OS + // } + + num = this->init_pool_threads_; + + // Set the busy_threads_ to the number of init_threads + // now. When they startup they will decrement themselves + // as they go into a wait state. + + this->busy_threads_ = 0; + + if (TAO_debug_level > 4) + { + ACE_DEBUG((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - DTP_Task::open() initialized with:\n") + ACE_TEXT ("TAO (%P|%t) - DTP_Task::open() init_threads_ \t\t: [%d]\n") + ACE_TEXT ("TAO (%P|%t) - DTP_Task::open() min_pool_threads_ \t\t: [%d]\n") + ACE_TEXT ("TAO (%P|%t) - DTP_Task::open() max_pool_threads_ \t\t: [%d]\n") + ACE_TEXT ("TAO (%P|%t) - DTP_Task::open() max_request_queue_depth_ \t: [%d]\n") + ACE_TEXT ("TAO (%P|%t) - DTP_Task::open() thread_stack_size_ \t\t: [%d]\n") + ACE_TEXT ("TAO (%P|%t) - DTP_Task::open() thread_idle_time_ \t\t: [%d]\n"), + this->init_pool_threads_, + this->min_pool_threads_, + this->max_pool_threads_, + this->max_request_queue_depth_, + this->thread_stack_size_, + this->thread_idle_time_.sec ()) + ); + } + + // We can't activate 0 threads. Make sure this isn't the case. + if (num < 1) + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("TAO (%P|%t) DTP_Task::open() failed to open. ") + ACE_TEXT ("num_threads (%u) is less-than 1.\n"), + num), + -1); + } + + // We need the lock acquired from here on out. + ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, guard, this->aw_lock_, -1); + + // We can assume that we are in the proper state to handle this open() + // call as long as we haven't been open()'ed before. + if (this->opened_) + { + //FUZZ: disable check_for_lack_ACE_OS + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("TAO (%P|%t) DTP_Task::open() failed to open. ") + ACE_TEXT ("Task has previously been open()'ed.\n")), + -1); + //FUZZ: enable check_for_lack_ACE_OS + } + // Create the stack size arrays if the stack size is set > 0. + + // Activate this task object with 'num' worker threads. + if (this->thread_stack_size_ == 0) + { + if (this->activate (THR_NEW_LWP | THR_DETACHED, num, 1) != 0) + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("(%P|%t) DTP_Task::open() failed to activate ") + ACE_TEXT ("(%d) worker threads.\n"), + num), + -1); + } + } + else + { + size_t * stack_sz_arr = new size_t[num]; + for (size_t z = 0; z < num; z++) + { + stack_sz_arr[z] = this->thread_stack_size_; + } + + if (this->activate (THR_NEW_LWP | THR_DETACHED, + num, + 1, + ACE_DEFAULT_THREAD_PRIORITY, + -1, + 0, + 0, + 0, + stack_sz_arr) != 0) + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("(%P|%t) DTP_Task::open() failed to activate ") + ACE_TEXT ("(%d) worker threads.\n"), + num), + -1); + } + + delete[] stack_sz_arr; + } + this->opened_ = true; + this->accepting_requests_ = true; + + return 0; +} + +bool +TAO_DTP_Task::request_ready (TAO::CSD::TP_Dispatchable_Visitor &v, + TAO::CSD::TP_Request_Handle &r) +{ + ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, guard, this->queue_lock_, false); + if (!this->queue_.is_empty()) + { + this->queue_.accept_visitor(v); + r = v.request(); + return !r.is_nil(); + } + return false; +} + +void +TAO_DTP_Task::clear_request (TAO::CSD::TP_Request_Handle &r) +{ + ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->queue_lock_); + --this->num_queue_requests_; + if (this->max_request_queue_depth_ > 0) + { + this->accepting_requests_ = true; + } + + if (TAO_debug_level > 4 ) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - DTP_Task::svc() ") + ACE_TEXT ("Decrementing num_queue_requests.") + ACE_TEXT ("New queue depth:%d\n"), + this->num_queue_requests_)); + } + + r->mark_as_ready (); +} + +int +TAO_DTP_Task::svc (void) +{ + ++this->busy_threads_; + if (TAO_debug_level > 4) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - DTP_Task::svc() ") + ACE_TEXT ("New thread created.\n"))); + } + + TAO::CSD::TP_Dispatchable_Visitor dispatchable_visitor; + while (!this->shutdown_) + { + TAO::CSD::TP_Request_Handle request; + + while (!this->shutdown_ && request.is_nil ()) + { + if (!this->request_ready (dispatchable_visitor, request)) + { + --this->busy_threads_; + + if (TAO_debug_level > 4) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - DTP_Task::svc() ") + ACE_TEXT ("Decrementing busy_threads_. ") + ACE_TEXT ("Busy thread count:%d\n"), + this->busy_threads_.value())); + } + + ACE_Time_Value tmp_sec = this->thread_idle_time_.to_absolute_time(); + + { + ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, guard, this->work_lock_, false); + int wait_state = this->thread_idle_time_.sec () == 0 + ? this->work_available_.wait () + : this->work_available_.wait (&tmp_sec); + + // Check for timeout + if (this->shutdown_) + return 0; + if (wait_state == -1) + { + if (errno != ETIME || + (this->thr_count() > this->min_pool_threads_ && + this->min_pool_threads_ > 0)) + { + if (TAO_debug_level > 4) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - DTP_Task::svc() ") + ACE_TEXT ("Existing thread expiring.\n"))); + } + return 0; + } + } + } + + ++this->busy_threads_; + if (TAO_debug_level > 4) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - DTP_Task::svc() ") + ACE_TEXT ("Incrementing busy_threads_. ") + ACE_TEXT ("Busy thread count:%d\n"), + this->busy_threads_.value ())); + } + } + } + + size_t count = this->thr_count (); + if ((this->busy_threads_ == count) && + ((this->max_pool_threads_ == 0) || + (count < this->max_pool_threads_))) + { + if (this->activate(THR_NEW_LWP | THR_DETACHED, + 1, + 1, + ACE_DEFAULT_THREAD_PRIORITY, + -1, + 0, + 0, + 0, + this->thread_stack_size_ == 0 ? 0 : + &this->thread_stack_size_) != 0) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("(%P|%t) DTP_Task::svc() failed to grow ") + ACE_TEXT ("to %d worker threads.\n"), count)); + } + else + { + if (TAO_debug_level > 4) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - DTP_Task::svc() ") + ACE_TEXT ("Growing threadcount. ") + ACE_TEXT ("New thread count:%d\n"), + this->thr_count ())); + } + } + } + + request->dispatch (); + this->clear_request (request); + dispatchable_visitor.reset (); + } + return 0; +} + + +int +TAO_DTP_Task::close(u_long flag) +{ + { + ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, guard, this->aw_lock_, 0); + if (flag == 0) + { + this->active_workers_.signal (); + return 0; + } + + if (!this->opened_) + { + return 0; + } + this->opened_ = false; + this->shutdown_ = true; + this->accepting_requests_ = false; + } + + { + ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, guard, this->work_lock_, 0); + this->work_available_.broadcast(); + } + + size_t in_task = (this->thr_mgr ()->task () == this) ? 1 : 0; + if (TAO_debug_level > 4) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - DTP_Task::close() ") + ACE_TEXT ("shutting down. in_task = %d, Count = %d \n"), + in_task, this->thr_count ())); + } + + while (this->thr_count () != in_task) + { + ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, guard, this->aw_lock_, 0); + this->active_workers_.wait (); + } + + { + ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, guard, this->queue_lock_, 0); + TAO::CSD::TP_Cancel_Visitor v; + this->queue_.accept_visitor (v); + } + return 0; +} + + +void +TAO_DTP_Task::set_init_pool_threads (size_t thr_count) +{ + this->init_pool_threads_ = thr_count; +} + +void +TAO_DTP_Task::set_min_pool_threads (size_t thr_count) +{ + this->min_pool_threads_ = thr_count; +} + +void +TAO_DTP_Task::set_max_pool_threads (size_t thr_count) +{ + this->max_pool_threads_ = thr_count; +} + +void +TAO_DTP_Task::set_thread_stack_size (size_t stack_sz) +{ + this->thread_stack_size_ = stack_sz; +} + +void +TAO_DTP_Task::set_thread_idle_time(ACE_Time_Value thr_timeout) +{ + this->thread_idle_time_ = thr_timeout; +} + +void +TAO_DTP_Task::set_max_request_queue_depth (size_t queue_depth) +{ + this->max_request_queue_depth_ = queue_depth; +} + +void +TAO_DTP_Task::cancel_servant (PortableServer::Servant servant) +{ + ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->queue_lock_); + + // Cancel the requests targeted for the provided servant. + TAO::CSD::TP_Cancel_Visitor cancel_visitor (servant); + this->queue_.accept_visitor (cancel_visitor); +} + +TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/tao/Dynamic_TP/DTP_Task.h b/TAO/tao/Dynamic_TP/DTP_Task.h new file mode 100644 index 00000000000..0b18950e75d --- /dev/null +++ b/TAO/tao/Dynamic_TP/DTP_Task.h @@ -0,0 +1,199 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file DTP_Task.h + * + * $Id$ + */ +//============================================================================= + +#ifndef TAO_DYNAMIC_TP_TASK_H +#define TAO_DYNAMIC_TP_TASK_H + +#include /**/ "ace/pre.h" + +#include "tao/Dynamic_TP/dynamic_tp_export.h" +#include "tao/Dynamic_TP/DTP_Config.h" +#include "tao/CSD_ThreadPool/CSD_TP_Queue.h" +#include "tao/CSD_ThreadPool/CSD_TP_Request.h" +#include "tao/CSD_ThreadPool/CSD_TP_Dispatchable_Visitor.h" +#include "tao/PortableServer/PortableServer.h" +#include "tao/Condition.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "ace/Task.h" +#include "ace/Synch.h" +#include "ace/Containers_T.h" +#include "ace/Vector_T.h" + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + + /** + * @class TP_Task + * + * @brief Active Object managing a queue of request objects. + * + * There are two types of "users" of a TP_Task object: + * + * 1) The TP_Strategy object that "owns" this task object. + * 2) The worker threads that "run" this task object as an + * "active object". + * + * The TP_Strategy object that "owns" this task object dictates + * when the worker threads are activated and when they are shutdown. It + * also injects requests into this task's queue via calls to the + * add_request() method. It is also the TP_Strategy object that + * dictates the number of worker threads to be activated via a call to + * the set_num_threads() method. + * + * The active object pattern is implemented via the use of the + * the ACE_Task_Base base class, and each worker thread will + * invoke this task's svc() method, and when the svc() returns, the + * worker thread will invoke this task's close() method (with the + * flag argument equal to 0). + */ + class TAO_Dynamic_TP_Export TAO_DTP_Task : public ACE_Task_Base + { + public: + + /// Default Constructor. + TAO_DTP_Task(); + + /// Virtual Destructor. + virtual ~TAO_DTP_Task(); + + struct Open_Args { + TAO_DTP_Definition task_thread_config; + }; + + + /// Put a request object on to the request queue. + /// Returns true if successful, false otherwise (it has been "rejected"). + bool add_request(TAO::CSD::TP_Request* request); + + /// Activate the worker threads + virtual int open(void* args = 0); + + /// The "mainline" executed by each worker thread. + virtual int svc(); + + virtual int close (u_long flag = 0); + + /// Set the thread and queue config. + + void set_init_pool_threads(size_t thr_count); + + void set_min_pool_threads(size_t thr_count); + + void set_max_pool_threads(size_t thr_count); + + void set_thread_stack_size(size_t stack_sz); + + void set_thread_idle_time(ACE_Time_Value thr_timeout); + + void set_max_request_queue_depth(size_t queue_depth); + + /// Get the thread and queue config. + + size_t get_init_pool_threads(); + + size_t get_min_pool_threads(); + + size_t get_max_pool_threads(); + + size_t get_max_request_queue_depth(); + + size_t get_thread_stack_size(); + + time_t get_thread_idle_time(); + + /// Cancel all requests that are targeted for the provided servant. + void cancel_servant (PortableServer::Servant servant); + + private: + /// get the next available request. Return true if one available, nonblocking + bool request_ready (TAO::CSD::TP_Dispatchable_Visitor &v, + TAO::CSD::TP_Request_Handle &r); + + /// release the request, reset the accepting flag if necessary + void clear_request (TAO::CSD::TP_Request_Handle &r); + + + + typedef TAO_SYNCH_MUTEX LockType; + typedef TAO_Condition<LockType> ConditionType; + + /// Lock used to synchronize the "active_workers_" condition + LockType aw_lock_; + /// Lock used to synchronize manipulation of the queue + LockType queue_lock_; + /// Lock used to synchronize the "work_available_" condition + LockType work_lock_; + + /// Condition used to signal worker threads that they may be able to + /// find a request in the queue_ that needs to be dispatched to a + /// servant that is currently "not busy". + /// This condition will be signal()'ed each time a new request is + /// added to the queue_, and also when a servant has become "not busy". + ConditionType work_available_; + + /// This condition will be signal()'ed each time the num_threads_ + /// data member has its value changed. This is used to keep the + /// close(1) invocation (ie, a shutdown request) blocked until all + /// of the worker threads have stopped running. + ConditionType active_workers_; + + /// Flag used to indicate when this task will (or will not) accept + /// requests via the the add_request() method. + bool accepting_requests_; + + /// Flag used to initiate a shutdown request to all worker threads. + bool shutdown_; + + /// Flag used to avoid multiple open() calls. + bool opened_; + + /// The number of requests in the local queue. + size_t num_queue_requests_; + + /// The number of currently active worker threads. + ACE_Atomic_Op <TAO_SYNCH_MUTEX, unsigned long> busy_threads_; + + /// The queue of pending servant requests (a.k.a. the "request queue"). + TAO::CSD::TP_Queue queue_; + + /// The low water mark for dynamic threads to settle to. + size_t init_pool_threads_; + + /// The low water mark for dynamic threads to settle to. + size_t min_pool_threads_; + + /// The high water mark for dynamic threads to be limited to. + size_t max_pool_threads_; + + /// If the max_pool_threads_ value has been met, then ORB requests coming in can be queued. + /// This is the maximum number that will be allowed. + size_t max_request_queue_depth_; + + /// This is the memory stack size allowable for each thread. + size_t thread_stack_size_; + + /// This is the maximum amount of time in seconds that an idle thread can + /// stay alive before being taken out of the pool. + ACE_Time_Value thread_idle_time_; + }; + + +TAO_END_VERSIONED_NAMESPACE_DECL + +#if defined (__ACE_INLINE__) +# include "tao/Dynamic_TP/DTP_Task.inl" +#endif /* __ACE_INLINE__ */ + +#include /**/ "ace/post.h" + +#endif /* TAO_DYNAMIC_TP_TASK_H */ diff --git a/TAO/tao/Dynamic_TP/DTP_Task.inl b/TAO/tao/Dynamic_TP/DTP_Task.inl new file mode 100644 index 00000000000..5b9eaafbd7d --- /dev/null +++ b/TAO/tao/Dynamic_TP/DTP_Task.inl @@ -0,0 +1,7 @@ +// -*- C++ -*- +// +// $Id$ + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/tao/Dynamic_TP/DTP_Thread_Lane_Resources_Manager.cpp b/TAO/tao/Dynamic_TP/DTP_Thread_Lane_Resources_Manager.cpp new file mode 100644 index 00000000000..1b70111c86b --- /dev/null +++ b/TAO/tao/Dynamic_TP/DTP_Thread_Lane_Resources_Manager.cpp @@ -0,0 +1,131 @@ +// $Id$ + +#include "tao/Dynamic_TP/DTP_Thread_Lane_Resources_Manager.h" + +#if defined (TAO_HAS_CORBA_MESSAGING) && TAO_HAS_CORBA_MESSAGING != 0 + +#include "tao/ORB_Core.h" +#include "tao/ORB_Core_TSS_Resources.h" +#include "tao/Acceptor_Registry.h" +#include "tao/Thread_Lane_Resources.h" +#include "tao/Dynamic_TP/DTP_Thread_Pool.h" +#include "tao/LF_Follower.h" +#include "tao/Leader_Follower.h" + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +TAO_DTP_Thread_Lane_Resources_Manager::TAO_DTP_Thread_Lane_Resources_Manager + (TAO_ORB_Core &orb_core) + : TAO_Thread_Lane_Resources_Manager (orb_core), + default_lane_resources_ (0), + tp_manager_ (0) +{ + // Create the default resources. + ACE_NEW (this->default_lane_resources_, + TAO_Thread_Lane_Resources (orb_core)); + + // Create the thread-pool manager. + ACE_NEW (this->tp_manager_, + TAO_DTP_Thread_Pool_Manager (orb_core)); + +} + +TAO_DTP_Thread_Lane_Resources_Manager::~TAO_DTP_Thread_Lane_Resources_Manager (void) +{ + // Delete the default resources. + delete this->default_lane_resources_; + + // Delete the thread-pool manager. + delete this->tp_manager_; +} + +int +TAO_DTP_Thread_Lane_Resources_Manager::open_default_resources (void) +{ + TAO_ORB_Parameters *params = + this->orb_core_->orb_params (); + + TAO_EndpointSet endpoint_set; + + params->get_endpoint_set (TAO_DEFAULT_LANE, endpoint_set); + + bool ignore_address = false; + + int const result = + this->default_lane_resources_->open_acceptor_registry (endpoint_set, + ignore_address); + + return result; +} + +void +TAO_DTP_Thread_Lane_Resources_Manager::finalize (void) +{ + // Finalize default resources. + this->default_lane_resources_->finalize (); +} + +void +TAO_DTP_Thread_Lane_Resources_Manager::shutdown_reactor (void) +{ + // Shutdown default reactors. + this->default_lane_resources_->shutdown_reactor (); + // This is the only reactor in use with this thread pool +} + +void +TAO_DTP_Thread_Lane_Resources_Manager::close_all_transports (void) +{ + // Shutdown default reactors. + this->default_lane_resources_->close_all_transports (); +} + +int +TAO_DTP_Thread_Lane_Resources_Manager::is_collocated (const TAO_MProfile &mprofile) +{ + return this->default_lane_resources_->is_collocated (mprofile); +} + +TAO_Thread_Lane_Resources & +TAO_DTP_Thread_Lane_Resources_Manager::lane_resources (void) +{ + return *this->default_lane_resources_; +} + +TAO_Thread_Lane_Resources & +TAO_DTP_Thread_Lane_Resources_Manager::default_lane_resources (void) +{ + return *this->default_lane_resources_; +} + +TAO_DTP_Thread_Pool_Manager & +TAO_DTP_Thread_Lane_Resources_Manager::tp_manager (void) +{ + return *this->tp_manager_; +} + +TAO_Thread_Lane_Resources_Manager * +TAO_DTP_Thread_Lane_Resources_Manager_Factory::create_thread_lane_resources_manager ( + TAO_ORB_Core &core) +{ + TAO_Thread_Lane_Resources_Manager *manager = 0; + + /// Create the RT Thread Lane Resources Manager. + ACE_NEW_RETURN (manager, + TAO_DTP_Thread_Lane_Resources_Manager (core), + 0); + + return manager; +} + +ACE_STATIC_SVC_DEFINE (TAO_DTP_Thread_Lane_Resources_Manager_Factory, + ACE_TEXT ("DTP_Thread_Lane_Resources_Manager_Factory"), + ACE_SVC_OBJ_T, + &ACE_SVC_NAME (TAO_DTP_Thread_Lane_Resources_Manager_Factory), + ACE_Service_Type::DELETE_THIS | ACE_Service_Type::DELETE_OBJ, + 0) +ACE_FACTORY_DEFINE (TAO_Dynamic_TP, TAO_DTP_Thread_Lane_Resources_Manager_Factory) + +TAO_END_VERSIONED_NAMESPACE_DECL + +#endif /* TAO_HAS_CORBA_MESSAGING && TAO_HAS_CORBA_MESSAGING != 0 */ diff --git a/TAO/tao/Dynamic_TP/DTP_Thread_Lane_Resources_Manager.h b/TAO/tao/Dynamic_TP/DTP_Thread_Lane_Resources_Manager.h new file mode 100644 index 00000000000..79278ec7726 --- /dev/null +++ b/TAO/tao/Dynamic_TP/DTP_Thread_Lane_Resources_Manager.h @@ -0,0 +1,124 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file DTP_Thread_Lane_Resources_Manager.h + * + * $Id$ + * + * @author Irfan Pyarali + */ +// =================================================================== + +#ifndef TAO_RT_THREAD_LANE_RESOURCES_MANAGER_H +#define TAO_RT_THREAD_LANE_RESOURCES_MANAGER_H + +#include /**/ "ace/pre.h" +#include "tao/orbconf.h" + +#if defined (TAO_HAS_CORBA_MESSAGING) && TAO_HAS_CORBA_MESSAGING != 0 + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "tao/Dynamic_TP/dynamic_tp_export.h" +#include "tao/Thread_Lane_Resources_Manager.h" +#include "ace/Service_Config.h" + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +class TAO_DTP_Thread_Pool_Manager; + +/** + * @class TAO_DTP_Thread_Lane_Resources_Manager + * + * @brief Manager for thread lane resources. + * + * \nosubgrouping + * + **/ +class TAO_Dynamic_TP_Export TAO_DTP_Thread_Lane_Resources_Manager : + public TAO_Thread_Lane_Resources_Manager +{ +public: + + /// Constructor. + TAO_DTP_Thread_Lane_Resources_Manager (TAO_ORB_Core &orb_core); + + /// Destructor. + ~TAO_DTP_Thread_Lane_Resources_Manager (void); + + /// Finalize resources. + void finalize (void); + + /// Open default resources. + int open_default_resources (void); + + /// Shutdown reactor. + void shutdown_reactor (void); + + /// Certain ORB policies such as dropping replies on shutdown + /// would need cleanup of transports to wake threads up. + void close_all_transports (void); + + /// Does @a mprofile belong to us? + int is_collocated (const TAO_MProfile &mprofile); + + /// @name Accessors + // @{ + + TAO_Thread_Lane_Resources &lane_resources (void); + + TAO_Thread_Lane_Resources &default_lane_resources (void); + + TAO_DTP_Thread_Pool_Manager &tp_manager (void); + + // @} + +private: + void operator= (const TAO_DTP_Thread_Lane_Resources_Manager &); + TAO_DTP_Thread_Lane_Resources_Manager (const TAO_DTP_Thread_Lane_Resources_Manager &); + +protected: + + /// Default lane resources. + TAO_Thread_Lane_Resources *default_lane_resources_; + + /// Thread Pool Manager. + TAO_DTP_Thread_Pool_Manager *tp_manager_; +}; + +/** + * @class TAO_DTP_Thread_Lane_Resources_Manager_Factory + * + * @brief This class is a factory for managers of thread resources. + * + * \nosubgrouping + * + **/ +class TAO_Dynamic_TP_Export TAO_DTP_Thread_Lane_Resources_Manager_Factory + : public TAO_Thread_Lane_Resources_Manager_Factory +{ +public: + + /// Factory method. + TAO_Thread_Lane_Resources_Manager *create_thread_lane_resources_manager ( + TAO_ORB_Core &core); + +}; + + + +ACE_STATIC_SVC_DECLARE_EXPORT (TAO_Dynamic_TP, + TAO_DTP_Thread_Lane_Resources_Manager_Factory) +ACE_FACTORY_DECLARE (TAO_Dynamic_TP, + TAO_DTP_Thread_Lane_Resources_Manager_Factory) + +TAO_END_VERSIONED_NAMESPACE_DECL + +#endif /* TAO_HAS_CORBA_MESSAGING && TAO_HAS_CORBA_MESSAGING != 0 */ + +#include /**/ "ace/post.h" + +#endif /* TAO_RT_THREAD_LANE_RESOURCES_MANAGER_H */ diff --git a/TAO/tao/Dynamic_TP/DTP_Thread_Pool.cpp b/TAO/tao/Dynamic_TP/DTP_Thread_Pool.cpp new file mode 100644 index 00000000000..9d03eb8cb48 --- /dev/null +++ b/TAO/tao/Dynamic_TP/DTP_Thread_Pool.cpp @@ -0,0 +1,456 @@ +// $Id$ + +#include "tao/Dynamic_TP/DTP_Thread_Pool.h" + +#if defined (TAO_HAS_CORBA_MESSAGING) && TAO_HAS_CORBA_MESSAGING != 0 + +#if ! defined (__ACE_INLINE__) +#include "tao/Dynamic_TP/DTP_Thread_Pool.inl" +#endif /* __ACE_INLINE__ */ + +#include "tao/Exception.h" +#include "tao/ORB_Core.h" +#include "tao/ORB_Core_TSS_Resources.h" +#include "tao/TSS_Resources.h" +#include "tao/ORB.h" +#include "tao/Acceptor_Registry.h" +#include "tao/debug.h" +#include "tao/LF_Follower.h" +#include "tao/Leader_Follower.h" +#include "ace/Auto_Ptr.h" + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +TAO_DTP_New_Leader_Generator::TAO_DTP_New_Leader_Generator ( + TAO_DTP_Thread_Pool &p) + : pool_ (p) +{ +} + +void +TAO_DTP_New_Leader_Generator::no_leaders_available (void) +{ + this->pool_.new_dynamic_thread (); +} + +TAO_DTP_Thread_Pool_Threads::TAO_DTP_Thread_Pool_Threads (TAO_DTP_Thread_Pool &p) + : ACE_Task_Base (p.manager ().orb_core ().thr_mgr ()), + pool_ (p) +{ +} + +int +TAO_DTP_Thread_Pool_Threads::svc (void) +{ + TAO_ORB_Core &orb_core = this->pool_.manager ().orb_core (); + if (orb_core.has_shutdown ()) + return 0; + + try + { + // Do the work + this->run (orb_core); + } + catch (const ::CORBA::Exception& ex) + { + // No point propagating this exception. Print it out. + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("orb->run() raised exception for thread %t\n"))); + + ex._tao_print_exception (""); + } + + return 0; +} + +int +TAO_DTP_Thread_Pool_Threads::run (TAO_ORB_Core &orb_core) +{ + CORBA::ORB_ptr orb = orb_core.orb (); + // A timeout is specified, run the ORB in an idle loop, if we + // don't handle any operations for the given timeout we just + // exit the loop and this thread ends itself. + ACE_Time_Value tv (this->pool_.dynamic_thread_time ()); + + while (!orb_core.has_shutdown ()) + { + bool has_work = orb->work_pending (tv); + if (!has_work && this->pool_.above_minimum ()) + { + // we've timed out, but the pool is not yet at the minimum + break; + } + + // Run the ORB for the specified timeout, this prevents looping + // between work_pending/handle_events + tv = this->pool_.dynamic_thread_time (); + orb->run (tv); + // Reset the idle timeout + tv = this->pool_.dynamic_thread_time (); + } + + if (TAO_debug_level > 7) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO Process %P Pool %d Thread %t\n") + ACE_TEXT ("Current number of dynamic threads left = %d; ") + ACE_TEXT ("DTP worker thread is ending!\n"), + this->pool_.id (), + this->thr_count () - 1)); + } + + return 0; +} + +bool +TAO_DTP_Thread_Pool::above_minimum (void) +{ + return this->definition_.min_threads_ > 0 && + (int)this->threads_.thr_count () > this->definition_.min_threads_; +} + +bool +TAO_DTP_Thread_Pool::new_dynamic_thread (void) +{ + // Note that we are checking this condition below without the lock + // held. + if (this->definition_.max_threads_ > 0 && + (int)this->threads_.thr_count () >= this->definition_.max_threads_) + return false; + + ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, + mon, + this->lock_, + false); + + if (!this->manager_.orb_core ().has_shutdown () && !this->shutdown_ && + (this->definition_.max_threads_ == -1 || + (int)this->threads_.thr_count () < this->definition_.max_threads_)) + { + if (TAO_debug_level > 7) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO Process %P Pool %d Thread %t\n") + ACE_TEXT ("Current number of threads = %d; ") + ACE_TEXT ("min threads = %d; max threads = %d\n") + ACE_TEXT ("No leaders available; DTP creating new leader!\n"), + this->id_, + this->threads_.thr_count (), + this->definition_.min_threads_, + this->definition_.max_threads_)); + + if (this->create_threads_i (1, THR_BOUND | THR_DETACHED)) + { + if (TAO_debug_level > 0) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("Pool %d Thread %t: ") + ACE_TEXT ("cannot create dynamic thread\n"), + this->id_)); + } + return false; + } + } + + return true; +} + +CORBA::ULong +TAO_DTP_Thread_Pool::current_threads (void) const +{ + ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, + mon, + this->lock_, + 0); + + return this->threads_.thr_count (); +} + +int +TAO_DTP_Thread_Pool::create_initial_threads (void) +{ + ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, + mon, + this->lock_, + 0); + + // Create initial threads. + // first, create the minimum number of threads as static + // if the min threads count is -1 that means all threads are static + + size_t count = (size_t)this->definition_.init_threads_; + size_t extra = 0; + if (this->definition_.min_threads_ != -1) + { + extra = count - (size_t) this->definition_.min_threads_; + count = (size_t) this->definition_.min_threads_; + } + + if (TAO_debug_level > 7) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) DTP_Thread_Pool::create_initial_threads ") + ACE_TEXT ("Creating %d static and %d dynamic threads\n"), + count, extra)); + } + + int result = this->create_threads_i (count, THR_NEW_LWP | THR_JOINABLE); + if (result != -1 && extra > 0) + { + result = this->create_threads_i (extra, THR_BOUND | THR_DETACHED); + } + return result; +} + +int +TAO_DTP_Thread_Pool::create_dynamic_threads (size_t count) +{ + ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, + mon, + this->lock_, + 0); + + return this->create_threads_i (count, THR_BOUND | THR_DETACHED); +} + +int +TAO_DTP_Thread_Pool::create_threads_i (size_t count, + long thread_flags) +{ + // Overwritten parameters. + int force_active = 1; + + // Default parameters. + int default_grp_id = -1; + ACE_Task_Base *default_task = 0; + ACE_hthread_t *default_thread_handles = 0; + void **default_stack = 0; + + // Setting stack size. + size_t *stack_size_array = 0; + ACE_NEW_RETURN (stack_size_array, + size_t[count], + -1); + size_t index; + for (index = 0; index != count; ++index) + stack_size_array[index] = + this->definition_.stack_size_; + + // Make sure the dynamically created stack size array is properly + // deleted. + ACE_Auto_Basic_Array_Ptr<size_t> auto_stack_size_array (stack_size_array); + + TAO_ORB_Core &orb_core = manager_.orb_core (); + + long flags = + thread_flags | + orb_core.orb_params ()->thread_creation_flags (); + + int default_priority = 0; + + // Activate the threads. + int result = + this->threads_.activate (flags, + count, + force_active, + default_grp_id, + default_priority, + default_task, + default_thread_handles, + default_stack, + stack_size_array); + return result; +} + +TAO_DTP_Thread_Pool::TAO_DTP_Thread_Pool (TAO_DTP_Thread_Pool_Manager &manager, + CORBA::ULong id, + TAO_DTP_Definition &def) + : manager_ (manager), + id_ (id), + shutdown_ (false), + definition_ (def), + threads_ (*this), + new_thread_generator_ (*this) +{ + manager_.orb_core ().leader_follower ().set_new_leader_generator ( + &new_thread_generator_); +} + +void +TAO_DTP_Thread_Pool::open (void) +{ + // Nothing to do for now +} + +TAO_DTP_Thread_Pool::~TAO_DTP_Thread_Pool (void) +{ +} + +void +TAO_DTP_Thread_Pool::shutting_down (void) +{ + ACE_GUARD (TAO_SYNCH_MUTEX, + mon, + this->lock_); + + // We are shutting down, this way we are not creating any more new dynamic + // threads + this->shutdown_ = true; +} + + +void +TAO_DTP_Thread_Pool::wait (void) +{ + this->threads_.wait (); +} + +#define TAO_THREAD_POOL_MANAGER_GUARD \ + ACE_GUARD_THROW_EX ( \ + TAO_SYNCH_MUTEX, \ + mon, \ + this->lock_, \ + CORBA::INTERNAL ( \ + CORBA::SystemException::_tao_minor_code ( \ + TAO_GUARD_FAILURE, \ + 0), \ + CORBA::COMPLETED_NO)); + +TAO_DTP_Thread_Pool_Manager::TAO_DTP_Thread_Pool_Manager (TAO_ORB_Core &orb_core) + : orb_core_ (orb_core), + thread_pools_ (), + thread_pool_id_counter_ (1), + lock_ () +{ +} + +TAO_DTP_Thread_Pool_Manager::~TAO_DTP_Thread_Pool_Manager (void) +{ + // Delete all the pools. + for (THREAD_POOLS::ITERATOR iterator = this->thread_pools_.begin (); + iterator != this->thread_pools_.end (); + ++iterator) + delete (*iterator).int_id_; +} + + +void +TAO_DTP_Thread_Pool_Manager::wait (void) +{ + for (THREAD_POOLS::ITERATOR iterator = this->thread_pools_.begin (); + iterator != this->thread_pools_.end (); + ++iterator) + (*iterator).int_id_->wait (); +} + +CORBA::ULong +TAO_DTP_Thread_Pool_Manager::create_threadpool (TAO_DTP_Definition &def) +{ + TAO_THREAD_POOL_MANAGER_GUARD; + + return this->create_threadpool_i (def); +} + +void +TAO_DTP_Thread_Pool_Manager::destroy_threadpool (CORBA::ULong threadpool) +{ + TAO_DTP_Thread_Pool *tao_thread_pool = 0; + + // The guard is just for the map, don't do a wait inside the guard, because + // during the wait other threads can try to access the thread pool manager + // also, this can be one of the threads we are waiting for, which then + // results in a deadlock + { + TAO_THREAD_POOL_MANAGER_GUARD; + + // Unbind the thread pool from the map. + int const result = this->thread_pools_.unbind (threadpool, tao_thread_pool); + + // If the thread pool is not found in our map. + if (result != 0) + return; //throw RTCORBA::RTORB::InvalidThreadpool (); + } + + // Mark the thread pool that we are shutting down. + tao_thread_pool->shutting_down (); + + // Wait for the threads. + tao_thread_pool->wait (); + + // Delete the thread pool. + delete tao_thread_pool; + +} + +CORBA::ULong +TAO_DTP_Thread_Pool_Manager::create_threadpool_i (TAO_DTP_Definition &def) +{ + // Create the thread pool. + TAO_DTP_Thread_Pool *thread_pool = 0; + + ACE_NEW_THROW_EX (thread_pool, + TAO_DTP_Thread_Pool (*this, + this->thread_pool_id_counter_, + def + ), + CORBA::NO_MEMORY ()); + + return this->create_threadpool_helper (thread_pool); +} + +CORBA::ULong +TAO_DTP_Thread_Pool_Manager::create_threadpool_helper (TAO_DTP_Thread_Pool *thread_pool) +{ + // Make sure of safe deletion in case of errors. + auto_ptr<TAO_DTP_Thread_Pool> safe_thread_pool (thread_pool); + + // Open the pool. + thread_pool->open (); + + // Create the static threads. + int result = thread_pool->create_initial_threads (); + + // Throw exception in case of errors. + if (result != 0) + { + throw ::CORBA::INTERNAL + ( + CORBA::SystemException::_tao_minor_code + ( + 0, //TAO_RTCORBA_THREAD_CREATION_LOCATION_CODE, + errno), + CORBA::COMPLETED_NO); + } + + // Bind thread to internal table. + result = this->thread_pools_.bind (this->thread_pool_id_counter_, thread_pool); + + TAO_ORB_Core_TSS_Resources &tss = + *this->orb_core_.get_tss_resources (); + // Associate the thread pool with the ORB for later retrieval + tss.lane_ = thread_pool; + + // + // Throw exception in case of errors. + if (result != 0) + throw ::CORBA::INTERNAL (); + + // + // Success. + // + + // No need to delete thread pool. + safe_thread_pool.release (); + + // Return current counter and perform post-increment. + return this->thread_pool_id_counter_++; +} + +TAO_ORB_Core & +TAO_DTP_Thread_Pool_Manager::orb_core (void) const +{ + return this->orb_core_; +} + +TAO_END_VERSIONED_NAMESPACE_DECL + +#endif /* TAO_HAS_CORBA_MESSAGING && TAO_HAS_CORBA_MESSAGING != 0 */ diff --git a/TAO/tao/Dynamic_TP/DTP_Thread_Pool.h b/TAO/tao/Dynamic_TP/DTP_Thread_Pool.h new file mode 100644 index 00000000000..6dae84f7fa4 --- /dev/null +++ b/TAO/tao/Dynamic_TP/DTP_Thread_Pool.h @@ -0,0 +1,249 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file DTP_Thread_Pool.h + * + * $Id$ + * + * @author Irfan Pyarali + * @author Johnny Willemsen + * @author Phil Mesnier + */ +// =================================================================== + +#ifndef TAO_DTP_THREAD_POOL_H +#define TAO_DTP_THREAD_POOL_H + +#include /**/ "ace/pre.h" +#include "tao/orbconf.h" + +#if defined (TAO_HAS_CORBA_MESSAGING) && TAO_HAS_CORBA_MESSAGING != 0 + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "ace/Hash_Map_Manager.h" +#include "tao/Thread_Lane_Resources.h" +#include "tao/Dynamic_TP/dynamic_tp_export.h" +#include "tao/Dynamic_TP/DTP_Config.h" +#include "tao/New_Leader_Generator.h" +#include "ace/Task.h" +#include "ace/Null_Mutex.h" + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +class TAO_ORB_Core; +class TAO_DTP_Thread_Pool; +class TAO_DTP_Thread_Pool_Manager; + +/** + * @class TAO_DTP_New_Leader_Generator + * + * @brief Class for creating dynamic threads. + * + * \nosubgrouping + * + **/ +class TAO_Dynamic_TP_Export TAO_DTP_New_Leader_Generator + : public TAO_New_Leader_Generator +{ +public: + + /// Constructor. + TAO_DTP_New_Leader_Generator (TAO_DTP_Thread_Pool &lane); + + /// Leader/Follower class uses this method to notify the system that + /// we are out of leaders. + void no_leaders_available (void); + +private: + + /// Pool associated with this leader generator. + TAO_DTP_Thread_Pool &pool_; +}; + +/** + * @class TAO_DTP_Thread_Pool_Threads + * + * @brief Class representing a static thread running in a thread lane. + * + * \nosubgrouping + * + **/ +class TAO_DTP_Thread_Pool_Threads : public ACE_Task_Base +{ +public: + + /// Constructor. + TAO_DTP_Thread_Pool_Threads (TAO_DTP_Thread_Pool &pool); + + /// Method executed when a thread is spawned. + int svc (void); + + /// Accessor to the pool to which this thread belongs to. + TAO_DTP_Thread_Pool &pool (void) const; + +protected: + /// Do the real work + virtual int run (TAO_ORB_Core &orb_core); + + /// Pool to which this thread belongs to. + TAO_DTP_Thread_Pool &pool_; +}; + + +/** + * @class TAO_DTP_Thread_Pool + * + * @brief Class representing the thread pool inside a thread pool + * manager. + * + * \nosubgrouping + * + **/ +class TAO_Dynamic_TP_Export TAO_DTP_Thread_Pool +{ +public: + TAO_DTP_Thread_Pool (TAO_DTP_Thread_Pool_Manager &manager, + CORBA::ULong id, + TAO_DTP_Definition &definition); + + /// Destructor. + ~TAO_DTP_Thread_Pool (void); + + /// Open the pool. + void open (void); + + /// Wait for threads to exit. + void wait (void); + + /// Mark this thread pool that we are shutting down. + void shutting_down (void); + + /// Create the initial threads - only called once. + int create_initial_threads (void); + + /// Called by the TAO_DTP_New_Leader_Generator to request a new dynamic + /// thread. + /** + * It can be that no thread can be created because the number of + * threads is equal to the maximum we can have or the Thread Lane + * is shutting down. + * @retval true A new thread is created + * @retval false No thread could be created + */ + bool new_dynamic_thread (void); + + /// Called by the run loop to determine if to expire a thread or not + /// when the dynamic timeout is reached. + bool above_minimum (void); + + /// @name Accessors + // @{ + + bool use_timeouts (void) const; + const ACE_Time_Value& dynamic_thread_time (void) const; + + TAO_DTP_Thread_Pool_Manager &manager (void) const; + CORBA::ULong id (void) const; + CORBA::ULong current_threads (void) const; + + // @} + +private: + + int create_threads_i (size_t count, long thread_flags); + + /// Create @a number_of_threads of dynamic threads. Can be called + /// multiple times. + int create_dynamic_threads (size_t count); + + TAO_DTP_Thread_Pool_Manager &manager_; + + CORBA::ULong id_; + + /// This boolean is set when we are shutting down, then we will not create + /// any new dynamic threads + bool shutdown_; + + TAO_DTP_Definition definition_; + + /// Array with all threads + TAO_DTP_Thread_Pool_Threads threads_; + + TAO_DTP_New_Leader_Generator new_thread_generator_; + + /// Lock to guard all members of the pool + mutable TAO_SYNCH_MUTEX lock_; +}; + +/** + * @class TAO_DTP_Thread_Pool_Manager + * + * @brief Class for managing thread pools. + * + * \nosubgrouping + * + **/ +class TAO_Dynamic_TP_Export TAO_DTP_Thread_Pool_Manager +{ +public: + + /// Constructor. + TAO_DTP_Thread_Pool_Manager (TAO_ORB_Core &orb_core); + + /// Destructor. + ~TAO_DTP_Thread_Pool_Manager (void); + + /// Wait for threads to exit. + void wait (void); + + /// Create a threadpool without lanes. + CORBA::ULong create_threadpool (TAO_DTP_Definition &def); + + /// Destroy a threadpool. + void destroy_threadpool (CORBA::ULong threadpool); + + /// Collection of thread pools. + typedef ACE_Hash_Map_Manager<CORBA::ULong, TAO_DTP_Thread_Pool *, + ACE_Null_Mutex> THREAD_POOLS; + + /// @name Accessors + // @{ + TAO_ORB_Core &orb_core (void) const; + // @} + +private: + + /// @name Helpers + // @{ + + CORBA::ULong + create_threadpool_i (TAO_DTP_Definition &def); + + CORBA::ULong + create_threadpool_helper (TAO_DTP_Thread_Pool *thread_pool); + // @} + +private: + + TAO_ORB_Core &orb_core_; + + THREAD_POOLS thread_pools_; + CORBA::ULong thread_pool_id_counter_; + TAO_SYNCH_MUTEX lock_; +}; + +TAO_END_VERSIONED_NAMESPACE_DECL + +#if defined (__ACE_INLINE__) +#include "tao/Dynamic_TP/DTP_Thread_Pool.inl" +#endif /* __ACE_INLINE__ */ + +#endif /* TAO_HAS_CORBA_MESSAGING && TAO_HAS_CORBA_MESSAGING != 0 */ + +#include /**/ "ace/post.h" + +#endif /* TAO_THREAD_POOL_H */ diff --git a/TAO/tao/Dynamic_TP/DTP_Thread_Pool.inl b/TAO/tao/Dynamic_TP/DTP_Thread_Pool.inl new file mode 100644 index 00000000000..9c28cc41e0e --- /dev/null +++ b/TAO/tao/Dynamic_TP/DTP_Thread_Pool.inl @@ -0,0 +1,43 @@ +// -*- C++ -*- +// +// $Id$ + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +ACE_INLINE +TAO_DTP_Thread_Pool & +TAO_DTP_Thread_Pool_Threads::pool (void) const +{ + return this->pool_; +} + +ACE_INLINE +TAO_DTP_Thread_Pool_Manager & +TAO_DTP_Thread_Pool::manager (void) const +{ + return this->manager_; +} + +ACE_INLINE +CORBA::ULong +TAO_DTP_Thread_Pool::id (void) const +{ + return this->id_; +} + +ACE_INLINE +bool +TAO_DTP_Thread_Pool::use_timeouts (void) const +{ + return this->definition_.max_threads_ > -1; +} + +ACE_INLINE +const ACE_Time_Value& +TAO_DTP_Thread_Pool::dynamic_thread_time (void) const +{ + return this->definition_.timeout_; +} + + +TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/tao/Dynamic_TP/Dynamic_TP.mpc b/TAO/tao/Dynamic_TP/Dynamic_TP.mpc new file mode 100644 index 00000000000..764cc76884b --- /dev/null +++ b/TAO/tao/Dynamic_TP/Dynamic_TP.mpc @@ -0,0 +1,10 @@ +//$Id$ + +project(Dynamic_TP) : taolib, tao_output, install, pi, csd_framework, csd_threadpool { + sharedname = TAO_Dynamic_TP + dynamicflags += TAO_DYNAMIC_TP_BUILD_DLL + + specific { + install_dir = tao/Dynamic_TP + } +} diff --git a/TAO/tao/Dynamic_TP/dynamic_tp_export.h b/TAO/tao/Dynamic_TP/dynamic_tp_export.h new file mode 100644 index 00000000000..3c6fd2ff524 --- /dev/null +++ b/TAO/tao/Dynamic_TP/dynamic_tp_export.h @@ -0,0 +1,58 @@ + +// -*- C++ -*- +// $Id$ +// Definition for Win32 Export directives. +// This file is generated automatically by generate_export_file.pl TAO_Dynamic_TP +// ------------------------------ +#ifndef TAO_DYNAMIC_TP_EXPORT_H +#define TAO_DYNAMIC_TP_EXPORT_H + +#include "ace/config-all.h" + +#if defined (ACE_AS_STATIC_LIBS) && !defined (TAO_DYNAMIC_TP_HAS_DLL) +# define TAO_DYNAMIC_TP_HAS_DLL 0 +#endif /* ACE_AS_STATIC_LIBS && TAO_DYNAMIC_TP_HAS_DLL */ + +#if !defined (TAO_DYNAMIC_TP_HAS_DLL) +# define TAO_DYNAMIC_TP_HAS_DLL 1 +#endif /* ! TAO_DYNAMIC_TP_HAS_DLL */ + +#if defined (TAO_DYNAMIC_TP_HAS_DLL) && (TAO_DYNAMIC_TP_HAS_DLL == 1) +# if defined (TAO_DYNAMIC_TP_BUILD_DLL) +# define TAO_Dynamic_TP_Export ACE_Proper_Export_Flag +# define TAO_DYNAMIC_TP_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T) +# define TAO_DYNAMIC_TP_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# else /* TAO_DYNAMIC_TP_BUILD_DLL */ +# define TAO_Dynamic_TP_Export ACE_Proper_Import_Flag +# define TAO_DYNAMIC_TP_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T) +# define TAO_DYNAMIC_TP_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# endif /* TAO_DYNAMIC_TP_BUILD_DLL */ +#else /* TAO_DYNAMIC_TP_HAS_DLL == 1 */ +# define TAO_Dynamic_TP_Export +# define TAO_DYNAMIC_TP_SINGLETON_DECLARATION(T) +# define TAO_DYNAMIC_TP_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +#endif /* TAO_DYNAMIC_TP_HAS_DLL == 1 */ + +// Set TAO_DYNAMIC_TP_NTRACE = 0 to turn on library specific tracing even if +// tracing is turned off for ACE. +#if !defined (TAO_DYNAMIC_TP_NTRACE) +# if (ACE_NTRACE == 1) +# define TAO_DYNAMIC_TP_NTRACE 1 +# else /* (ACE_NTRACE == 1) */ +# define TAO_DYNAMIC_TP_NTRACE 0 +# endif /* (ACE_NTRACE == 1) */ +#endif /* !TAO_DYNAMIC_TP_NTRACE */ + +#if (TAO_DYNAMIC_TP_NTRACE == 1) +# define TAO_DYNAMIC_TP_TRACE(X) +#else /* (TAO_DYNAMIC_TP_NTRACE == 1) */ +# if !defined (ACE_HAS_TRACE) +# define ACE_HAS_TRACE +# endif /* ACE_HAS_TRACE */ +# define TAO_DYNAMIC_TP_TRACE(X) ACE_TRACE_IMPL(X) +# include "ace/Trace.h" +#endif /* (TAO_DYNAMIC_TP_NTRACE == 1) */ + +#endif /* TAO_DYNAMIC_TP_EXPORT_H */ + +// End of auto generated file. diff --git a/TAO/tao/IIOP_Profile.cpp b/TAO/tao/IIOP_Profile.cpp index 512d80f5afe..79e01c083bc 100644 --- a/TAO/tao/IIOP_Profile.cpp +++ b/TAO/tao/IIOP_Profile.cpp @@ -474,7 +474,7 @@ TAO_IIOP_Profile::add_generic_endpoint (TAO_Endpoint *endp) } char * -TAO_IIOP_Profile::to_string (void) +TAO_IIOP_Profile::to_string (void) const { // corbaloc:iiop:1.2@host:port,iiop:1.2@host:port,.../key diff --git a/TAO/tao/IIOP_Profile.h b/TAO/tao/IIOP_Profile.h index ebb886e9958..1bb6fb16d10 100644 --- a/TAO/tao/IIOP_Profile.h +++ b/TAO/tao/IIOP_Profile.h @@ -95,7 +95,7 @@ public: virtual char object_key_delimiter (void) const; /// Template methods. Please see Profile.h for documentation. - virtual char * to_string (void); + virtual char * to_string (void) const; /// Encode endpoints for RT profiles, using a single TAO_TAG_ENDPOINT /// component. diff --git a/TAO/tao/IIOP_Transport.cpp b/TAO/tao/IIOP_Transport.cpp index 3dc71149072..c4cb2025e99 100644 --- a/TAO/tao/IIOP_Transport.cpp +++ b/TAO/tao/IIOP_Transport.cpp @@ -166,6 +166,8 @@ TAO_IIOP_Transport::recv (char *buf, size_t len, const ACE_Time_Value *max_wait_time) { + this->connection_closed_on_read_ = false; + ssize_t const n = this->connection_handler_->peer ().recv (buf, len, max_wait_time); @@ -196,6 +198,7 @@ TAO_IIOP_Transport::recv (char *buf, // @@ What are the other error handling here?? else if (n == 0) { + this->connection_closed_on_read_ = true; return -1; } diff --git a/TAO/tao/IORManipulation/IORManipulation.cpp b/TAO/tao/IORManipulation/IORManipulation.cpp index 51b83283892..cbeb0e36bec 100644 --- a/TAO/tao/IORManipulation/IORManipulation.cpp +++ b/TAO/tao/IORManipulation/IORManipulation.cpp @@ -27,9 +27,9 @@ TAO_IOR_Manipulation_impl::merge_iors ( { // we need to create a new CORBA::Object which has the union of the // two profile lists. However, if any profiles are duplicates (i.e. in - // bott lisis) then an exception is raised. + // both lists) then an exception is raised. - // Deterinine how many profiles we have + // Determine how many profiles we have // Get an estimate of the size - pfile count could change since we // neither lock nor get a copy in this loop. CORBA::ULong i, count=0; @@ -56,12 +56,12 @@ TAO_IOR_Manipulation_impl::merge_iors ( for (i = 1; i < iors.length () ; i++) { - // this gets a copy of the MProfile, hense the auto_ptr; + // this gets a copy of the MProfile, hence the auto_ptr; ACE_auto_ptr_reset (tmp_pfiles, iors[i]->_stubobj ()->make_profiles ()); - // check to see if any of the profile in tmp_pfiles are already + // check to see if any of the profiles in tmp_pfiles are already // in Merged_Profiles. If so raise exception. if (Merged_Profiles.is_equivalent (tmp_pfiles.get ())) throw TAO_IOP::Duplicate (); diff --git a/TAO/tao/ImR_Client/ImR_Client.cpp b/TAO/tao/ImR_Client/ImR_Client.cpp index 010b938b876..810872ab321 100644 --- a/TAO/tao/ImR_Client/ImR_Client.cpp +++ b/TAO/tao/ImR_Client/ImR_Client.cpp @@ -2,6 +2,7 @@ #include "tao/ImR_Client/ImR_Client.h" +#include "ace/Vector_T.h" #include "tao/debug.h" #include "tao/ORB_Core.h" #include "tao/Stub.h" @@ -10,9 +11,193 @@ #include "tao/PortableServer/Non_Servant_Upcall.h" #include "tao/ImR_Client/ServerObject_i.h" #include "tao/ImR_Client/ImplRepoC.h" +#include "tao/IORManipulation/IORManip_Loader.h" TAO_BEGIN_VERSIONED_NAMESPACE_DECL +namespace +{ + char* find_delimiter (char* const ior, const char delimiter) + { + // Search for "corbaloc:" alone, without the protocol. This code + // should be protocol neutral. + const char corbaloc[] = ACE_TEXT_ALWAYS_CHAR ("corbaloc:"); + char *pos = ACE_OS::strstr (ior, corbaloc); + pos = ACE_OS::strchr (pos + sizeof (corbaloc), ':'); + + pos = ACE_OS::strchr (pos + 1, delimiter); + + return pos; + } + + CORBA::Object_ptr combine (TAO_ORB_Core& orb_core, + const TAO_Profile& profile, + const char* const key_str, + const char* type_id) + { + CORBA::String_var profile_str = profile.to_string (); + +// if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("************** IMR partial IOR =\n%C\n"), + profile_str.in ())); + + char* const pos = find_delimiter (profile_str.inout (), + profile.object_key_delimiter ()); + if (pos) + pos[1] = 0; // Crop the string. + else + { + if (TAO_debug_level > 0) + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("Could not parse ImR IOR, skipping ImRification\n"))); + return CORBA::Object::_nil(); + } + + ACE_CString ior (profile_str.in ()); + + // Add the key. + ior += key_str; + +// if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("************** ImR-ified IOR =\n%C\n\n"), + ior.c_str ())); + + CORBA::Object_ptr obj = orb_core.orb ()->string_to_object (ior.c_str ()); + obj->_stubobj()->type_id = type_id; + return obj; + } + + class ImRifyProfiles + { + public: + ImRifyProfiles (const TAO_MProfile& base_profiles, + const TAO_Profile* const profile_in_use, + TAO_ORB_Core& orb_core, + const char* const key_str, + const char* type_id) + : base_profiles_ (base_profiles), + profile_in_use_ (profile_in_use), + orb_core_ (orb_core), + key_str_ (key_str), + type_id_ (type_id), + objs_ (base_profiles.profile_count()), + list_buffer_ (new CORBA::Object_ptr[base_profiles.profile_count()]), + ior_list_ (base_profiles.profile_count (), + base_profiles.profile_count (), + list_buffer_, + 0) + { + } + + CORBA::Object_ptr combined_ior () + { + const CORBA::ULong pcount = base_profiles_.profile_count (); + for (CORBA::ULong i = 0; i < pcount; ++i) + { + if (!combine_profile (i)) + { + return default_obj ( + ACE_TEXT_ALWAYS_CHAR ("could not resolve IORManipulation")); + } + } + + CORBA::Object_var IORM = orb_core_.orb () + ->resolve_initial_references (TAO_OBJID_IORMANIPULATION, 0); + + if (CORBA::is_nil (IORM.in ())) + { + return default_obj ( + ACE_TEXT_ALWAYS_CHAR ("could not resolve IORManipulation")); + } + + TAO_IOP::TAO_IOR_Manipulation_var iorm = + TAO_IOP::TAO_IOR_Manipulation::_narrow (IORM.in ()); + + if (CORBA::is_nil (iorm.in ())) + { + return default_obj ( + ACE_TEXT_ALWAYS_CHAR ("could not narrow IORManipulation")); + } + + try + { + return iorm->merge_iors(ior_list_); + } + catch (const ::CORBA::Exception& ) + { + return default_obj ( + ACE_TEXT_ALWAYS_CHAR ("could not ImRify object with all profiles.")); + } + } + private: + bool combine_profile(const CORBA::ULong i) + { + try + { + // store the combined profile+key + list_buffer_[i] = combine (orb_core_, + *(base_profiles_.get_profile (i)), + key_str_, + type_id_); + // manage the memory + objs_[i] = list_buffer_[i]; + + return true; + } + catch (const ::CORBA::Exception& ) + { + return false; + } + } + + CORBA::Object_ptr default_obj(const char* desc) + { + const CORBA::ULong pcount = base_profiles_.profile_count (); + const char* info = + ACE_TEXT ("because couldn't find ImR profile_in_use in profiles"); + + // identify the profile in use to see if we can default to + // that profiles partial ImR-ification + for (CORBA::ULong i = 0; i < pcount; ++i) + { + if (profile_in_use_ == base_profiles_.get_profile (i)) + { + // if there is no object then try one last time to combine + // the profile + if (CORBA::is_nil(objs_[i].in ()) && !combine_profile (i)) + { + info = ACE_TEXT ("because couldn't ImR-ify profile_in_use"); + break; + } + ACE_ERROR((LM_ERROR, + ACE_TEXT("ERROR: %C. ") + ACE_TEXT("Defaulting to ImR-ifying profile_in_use\n"), + desc)); + return objs_[i]._retn (); + } + } + + ACE_ERROR((LM_ERROR, + ACE_TEXT ("ERROR: %C, ") + ACE_TEXT ("but cannot default to ImR-ifying profile_in_use %C\n"), + desc, + info)); + return CORBA::Object::_nil(); + } + + const TAO_MProfile& base_profiles_; + const TAO_Profile* const profile_in_use_; + TAO_ORB_Core& orb_core_; + const char* const key_str_; + const char* const type_id_; + ACE_Vector<CORBA::Object_var> objs_; + CORBA::Object_ptr* const list_buffer_; + TAO_IOP::TAO_IOR_Manipulation::IORList ior_list_; + }; +} + namespace TAO { namespace ImR_Client @@ -38,7 +223,18 @@ namespace TAO } if (TAO_debug_level > 0) - ACE_DEBUG ((LM_DEBUG, "Notifying ImR of startup\n")); + { + ACE_CString imr_info; + if (TAO_debug_level > 1) + { + CORBA::ORB_ptr orb = poa->orb_core ().orb (); + CORBA::String_var ior = orb->object_to_string (imr.in ()); + imr_info = ACE_CString (", IMR IOR=") + ior.in (); + } + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("Notifying ImR of startup%s\n"), + imr_info.c_str ())); + } ImplementationRepository::Administration_var imr_locator; @@ -51,7 +247,7 @@ namespace TAO ImplementationRepository::Administration::_narrow (imr.in ()); } - if (CORBA::is_nil(imr_locator.in ())) + if (CORBA::is_nil (imr_locator.in ())) { ACE_ERROR ((LM_ERROR, ACE_TEXT ("(%P|%t) ERROR: Narrowed IMR initial reference ") @@ -82,7 +278,7 @@ namespace TAO poa->server_priority (), wait_occurred_restart_call_ignored); - CORBA::Object_var obj = root_poa->id_to_reference_i (id.in (), false); + CORBA::Object_var obj = root_poa->id_to_reference_i (id.in (), false); ImplementationRepository::ServerObject_var svr = ImplementationRepository::ServerObject::_narrow (obj.in ()); @@ -93,24 +289,23 @@ namespace TAO return; } - CORBA::String_var ior = - svr->_stubobj ()->profile_in_use ()->to_string (); + CORBA::String_var full_ior = root_poa->_get_orb()->object_to_string (obj.in ()); + TAO_Profile& profile = *(svr->_stubobj ()->profile_in_use ()); + CORBA::String_var ior = profile.to_string(); + ACE_DEBUG((LM_INFO, + "\n\nfull_ior=<%s>\n\nior=<%s>\n\n", + full_ior.in(), + ior.in())); - // Search for "corbaloc:" alone, without the protocol. This code - // should be protocol neutral. - const char corbaloc[] = "corbaloc:"; - char *pos = ACE_OS::strstr (ior.inout (), corbaloc); - pos = ACE_OS::strchr (pos + sizeof (corbaloc), ':'); + char* const pos = find_delimiter (ior.inout (), + profile.object_key_delimiter ()); - pos = ACE_OS::strchr (pos + 1, - svr->_stubobj ()->profile_in_use ()->object_key_delimiter ()); - - ACE_CString partial_ior(ior.in (), (pos - ior.in()) + 1); + const ACE_CString partial_ior (ior.in (), (pos - ior.in ()) + 1); if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG, - "Informing IMR that we are running at: %C\n", - partial_ior.c_str())); + ACE_TEXT ("Informing IMR that we are running at: %C\n"), + partial_ior.c_str ())); try { @@ -122,16 +317,16 @@ namespace TAO ACE_CString name; if (serverId.empty ()) { - name = poa->name(); + name = poa->name (); } else { - name = serverId + ":" + poa->name(); + name = serverId + ":" + poa->name (); } imr_locator->server_is_running (name.c_str (), - partial_ior.c_str(), - svr.in()); + partial_ior.c_str (), + svr.in ()); } catch (const ::CORBA::SystemException&) { @@ -145,7 +340,8 @@ namespace TAO } if (TAO_debug_level > 0) - ACE_DEBUG ((LM_DEBUG, "Successfully notified ImR of Startup\n")); + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("Successfully notified ImR of Startup\n"))); } void @@ -165,7 +361,7 @@ namespace TAO { CORBA::String_var poaname = poa->the_name (); ACE_DEBUG ((LM_DEBUG, - "Notifying IMR of Shutdown server:%s\n", + ACE_TEXT ("Notifying IMR of Shutdown server:%s\n"), poaname.in ())); } @@ -177,7 +373,7 @@ namespace TAO ImplementationRepository::Administration_var imr_locator = ImplementationRepository::Administration::_narrow (imr.in ()); - imr_locator->server_is_shutting_down (poa->name().c_str ()); + imr_locator->server_is_shutting_down (poa->name ().c_str ()); } catch (const ::CORBA::COMM_FAILURE&) { @@ -185,13 +381,17 @@ namespace TAO // configured to drop replies during shutdown (it does by default in // the LF model) we get a COMM_FAILURE exception which we ignore if (TAO_debug_level > 0) - ACE_DEBUG((LM_DEBUG, "Ignoring COMM_FAILURE while unregistering from ImR.\n")); + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("Ignoring COMM_FAILURE while unregistering") + ACE_TEXT ("from ImR.\n"))); } catch (const ::CORBA::TRANSIENT&) { // Similarly, there are cases where we could get a TRANSIENT. if (TAO_debug_level > 0) - ACE_DEBUG((LM_DEBUG, "Ignoring TRANSIENT while unregistering from ImR.\n")); + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("Ignoring TRANSIENT while unregistering") + ACE_TEXT ("from ImR.\n"))); } catch (const ::CORBA::Exception& ex) { @@ -202,9 +402,11 @@ namespace TAO if (this->server_object_) { - PortableServer::POA_var default_poa = this->server_object_->_default_POA (); + PortableServer::POA_var default_poa = + this->server_object_->_default_POA (); - TAO_Root_POA *root_poa = dynamic_cast <TAO_Root_POA*> (default_poa.in ()); + TAO_Root_POA *root_poa = + dynamic_cast <TAO_Root_POA*> (default_poa.in ()); if (!root_poa) { @@ -214,7 +416,7 @@ namespace TAO PortableServer::ObjectId_var id = root_poa->servant_to_id_i (this->server_object_); - root_poa->deactivate_object_i (id.in()); + root_poa->deactivate_object_i (id.in ()); this->server_object_ = 0; } @@ -227,16 +429,63 @@ namespace TAO int ImR_Client_Adapter_Impl::Initializer (void) { - TAO_Root_POA::imr_client_adapter_name ("Concrete_ImR_Client_Adapter"); + TAO_Root_POA::imr_client_adapter_name ( + ACE_TEXT_ALWAYS_CHAR ("Concrete_ImR_Client_Adapter")); + + return ACE_Service_Config::process_directive ( + ace_svc_desc_ImR_Client_Adapter_Impl); + } + + CORBA::Object_ptr + ImR_Client_Adapter_Impl::imr_key_to_object(TAO_Root_POA* poa, + const TAO::ObjectKey &key, + const char* type_id) const + { + TAO_ORB_Core& orb_core = poa->orb_core (); + // Check to see if we alter the IOR. + CORBA::Object_var imr = orb_core.implrepo_service (); + + if (CORBA::is_nil (imr.in ()) + || !imr->_stubobj () + || !imr->_stubobj ()->profile_in_use ()) + { + if (TAO_debug_level > 1) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("Missing ImR IOR, will not use the ImR\n"))); + } + return CORBA::Object::_nil(); + } + + const TAO_MProfile& base_profiles = imr->_stubobj ()->base_profiles (); + CORBA::String_var key_str; + TAO::ObjectKey::encode_sequence_to_string (key_str.inout (), key); + + // if there is only one profile, no need to use IORManipulation + if (base_profiles.profile_count() == 1) + { + return combine(orb_core, + *base_profiles.get_profile(0), + key_str.in(), + ACE_TEXT_ALWAYS_CHAR (type_id)); + } + + // need to combine each profile in the ImR with the key and + // then merge them all together into one ImR-ified ior + ImRifyProfiles imrify (base_profiles, + imr->_stubobj ()->profile_in_use (), + orb_core, + key_str, + ACE_TEXT_ALWAYS_CHAR (type_id)); - return ACE_Service_Config::process_directive (ace_svc_desc_ImR_Client_Adapter_Impl); + return imrify.combined_ior (); } } } ACE_STATIC_SVC_DEFINE ( ImR_Client_Adapter_Impl, - ACE_TEXT ("Concrete_ImR_Client_Adapter"), + ACE_TEXT_ALWAYS_CHAR ("Concrete_ImR_Client_Adapter"), ACE_SVC_OBJ_T, &ACE_SVC_NAME (ImR_Client_Adapter_Impl), ACE_Service_Type::DELETE_THIS | ACE_Service_Type::DELETE_OBJ, diff --git a/TAO/tao/ImR_Client/ImR_Client.h b/TAO/tao/ImR_Client/ImR_Client.h index ed270a2af03..02185598e6d 100644 --- a/TAO/tao/ImR_Client/ImR_Client.h +++ b/TAO/tao/ImR_Client/ImR_Client.h @@ -59,6 +59,11 @@ namespace TAO /// ImplRepo helper method, notify the ImplRepo on shutdown virtual void imr_notify_shutdown (TAO_Root_POA* poa); + /// ImplRepo helper method, create an IMR-ified object for a + /// key with a given type + virtual CORBA::Object_ptr imr_key_to_object(TAO_Root_POA* poa, + const TAO::ObjectKey &key, + const char *type_id) const; private: /// Implementation Repository Server Object ServerObject_i *server_object_; diff --git a/TAO/tao/ImR_Client/ImR_Client.mpc b/TAO/tao/ImR_Client/ImR_Client.mpc index 26d5027ea46..4350825cc33 100644 --- a/TAO/tao/ImR_Client/ImR_Client.mpc +++ b/TAO/tao/ImR_Client/ImR_Client.mpc @@ -24,7 +24,7 @@ project(*idl) : tao_versioning_idl_defaults, install { } } -project(ImR_Client) : taolib, tao_output, install, portableserver, taoidldefaults { +project(ImR_Client) : taolib, tao_output, install, portableserver, taoidldefaults, iormanip { after += *idl sharedname = TAO_ImR_Client dynamicflags += TAO_IMR_CLIENT_BUILD_DLL diff --git a/TAO/tao/Invocation_Adapter.cpp b/TAO/tao/Invocation_Adapter.cpp index f85187b0172..310cec2dad1 100644 --- a/TAO/tao/Invocation_Adapter.cpp +++ b/TAO/tao/Invocation_Adapter.cpp @@ -15,6 +15,7 @@ #include "tao/TAOC.h" #include "tao/SystemException.h" #include "tao/Collocation_Resolver.h" +#include "tao/Invocation_Retry_State.h" #include "ace/Service_Config.h" #if !defined (__ACE_INLINE__) @@ -69,6 +70,8 @@ namespace TAO max_wait_time= &tmp_wait_time; } + TAO::Invocation_Retry_State retry_state (*stub); + while (status == TAO_INVOKE_START || status == TAO_INVOKE_RESTART) { // Default we go to remote @@ -95,7 +98,8 @@ namespace TAO this->invoke_remote_i (stub, details, effective_target, - max_wait_time); + max_wait_time, + &retry_state); } else { @@ -228,7 +232,8 @@ namespace TAO Invocation_Adapter::invoke_remote_i (TAO_Stub *stub, TAO_Operation_Details &details, CORBA::Object_var &effective_target, - ACE_Time_Value *&max_wait_time) + ACE_Time_Value *&max_wait_time, + Invocation_Retry_State *retry_state) { (void) this->set_response_flags (stub, details); @@ -270,7 +275,8 @@ namespace TAO return this->invoke_twoway (details, effective_target, resolver, - max_wait_time); + max_wait_time, + retry_state); } } @@ -281,7 +287,8 @@ namespace TAO Invocation_Adapter::invoke_twoway (TAO_Operation_Details &details, CORBA::Object_var &effective_target, Profile_Transport_Resolver &r, - ACE_Time_Value *&max_wait_time) + ACE_Time_Value *&max_wait_time, + Invocation_Retry_State *retry_state) { // Simple sanity check if (this->mode_ != TAO_SYNCHRONOUS_INVOCATION || @@ -294,7 +301,10 @@ namespace TAO CORBA::COMPLETED_NO); } - TAO::Synch_Twoway_Invocation synch (this->target_, r, details); + TAO::Synch_Twoway_Invocation synch (this->target_, r, details, + true); + + synch.set_retry_state (retry_state); Invocation_Status const status = synch.remote_twoway (max_wait_time); diff --git a/TAO/tao/Invocation_Adapter.h b/TAO/tao/Invocation_Adapter.h index f539c28de45..b1ec5f7db19 100644 --- a/TAO/tao/Invocation_Adapter.h +++ b/TAO/tao/Invocation_Adapter.h @@ -47,6 +47,7 @@ namespace TAO class Argument; struct Exception_Data; class Profile_Transport_Resolver; + class Invocation_Retry_State; /** * @class Invocation_Adapter @@ -124,7 +125,9 @@ namespace TAO * @param ex_count Number of elements in the array. */ virtual void invoke (TAO::Exception_Data *ex, unsigned long ex_count); + protected: + /** * The stub pointer passed to this call has all the details about * the object to which the invocation needs to be routed to. The @@ -163,7 +166,8 @@ namespace TAO TAO_Stub *stub, TAO_Operation_Details &details, CORBA::Object_var &effective_target, - ACE_Time_Value *&max_wait_time); + ACE_Time_Value *&max_wait_time, + Invocation_Retry_State *retry_state = 0); /// Make a collocated call. /** @@ -193,7 +197,8 @@ namespace TAO TAO_Operation_Details &details, CORBA::Object_var &effective_target, Profile_Transport_Resolver &r, - ACE_Time_Value *&max_wait_time); + ACE_Time_Value *&max_wait_time, + Invocation_Retry_State *retry_state = 0); /// Helper method to make a one way invocation. /** diff --git a/TAO/tao/Invocation_Retry_Params.cpp b/TAO/tao/Invocation_Retry_Params.cpp new file mode 100644 index 00000000000..4d966613d36 --- /dev/null +++ b/TAO/tao/Invocation_Retry_Params.cpp @@ -0,0 +1,20 @@ +// -*- C++ -*- +// +// $Id$ + +#include "tao/Invocation_Retry_Params.h" +#include "tao/Invocation_Utils.h" + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +TAO::Invocation_Retry_Params::Invocation_Retry_Params (void) + : forward_on_reply_closed_limit_ (0) + , init_retry_delay_ (0, 100000) // Set default to 0.1 seconds +{ + this->forward_on_exception_limit_[FOE_OBJECT_NOT_EXIST] = 0; + this->forward_on_exception_limit_[FOE_COMM_FAILURE] = 0; + this->forward_on_exception_limit_[FOE_TRANSIENT] = 0; + this->forward_on_exception_limit_[FOE_INV_OBJREF] = 0; +} + +TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/tao/Invocation_Retry_Params.h b/TAO/tao/Invocation_Retry_Params.h new file mode 100644 index 00000000000..659ad4f7655 --- /dev/null +++ b/TAO/tao/Invocation_Retry_Params.h @@ -0,0 +1,61 @@ +/* -*- C++ -*- $Id$ */ +//============================================================================= +/** + * @file Invocation_Retry_Params.h + * + * $Id$ + * + * @author Byron Harris (harrisb@ociweb.com) + */ +//============================================================================= + +#ifndef TAO_INVOCATION_RETRY_PARAMS_H +#define TAO_INVOCATION_RETRY_PARAMS_H + +#include "tao/orbconf.h" +#include "ace/Array_Map.h" + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +namespace TAO +{ + /** + * @struct Invocation_Retry_Params + * + * @brief Contains the invocation retry parameters used when encountering + * CORBA exceptions. + * The parameters can be specified using either the Client_Strategy_Factory + * service given in the service configuration file or through the command line. + * Any command line parameter overrides the corresponding option in the service + * configurator file. + */ + struct Invocation_Retry_Params + { + Invocation_Retry_Params(); + + typedef ACE_Array_Map<int, int> exception_limit_map_type; + + /** + * The maximum number of retry attempts per exception type + * when exceptions are encountered. The profiles are + * cycled through during each attempt. + */ + exception_limit_map_type forward_on_exception_limit_; + + /** + * The maximum number of times to retry a an invocation + * if the the connection to the server is closed when + * trying to get a reply. + */ + int forward_on_reply_closed_limit_; + + /** + * The delay to use between cycles of base and forward profiles. + */ + ACE_Time_Value init_retry_delay_; + }; +} + +TAO_END_VERSIONED_NAMESPACE_DECL + +#endif /* TAO_INVOCATION_RETRY_PARAMS_H*/ diff --git a/TAO/tao/Invocation_Retry_State.cpp b/TAO/tao/Invocation_Retry_State.cpp new file mode 100644 index 00000000000..7204250846a --- /dev/null +++ b/TAO/tao/Invocation_Retry_State.cpp @@ -0,0 +1,176 @@ +// -*- C++ -*- +// +// $Id$ + +#include "tao/Invocation_Retry_State.h" +#include "tao/ORB_Core.h" +#include "tao/Client_Strategy_Factory.h" + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +namespace +{ + void retry_limit_calc (int ex, + TAO::Invocation_Retry_Params &command_line_params, + TAO::Invocation_Retry_Params &client_factory_params, + TAO::Invocation_Retry_Params &result) + { + if (command_line_params.forward_on_exception_limit_[ex] != + result.forward_on_exception_limit_[ex]) + result.forward_on_exception_limit_[ex] = + command_line_params.forward_on_exception_limit_[ex]; + else if (client_factory_params.forward_on_exception_limit_[ex] != + result.forward_on_exception_limit_[ex]) + result.forward_on_exception_limit_[ex] = + client_factory_params.forward_on_exception_limit_[ex]; + } + + /// Calculate the retry parameters by giving a command line parameter + /// precedence over the corresponding client strategy factory parameter. + /// result is assumed to be passed with default values + void retry_params_calc (TAO::Invocation_Retry_Params &command_line_params, + TAO::Invocation_Retry_Params &client_factory_params, + TAO::Invocation_Retry_Params &result) + { + + // Retry delay + if (command_line_params.init_retry_delay_ != + result.init_retry_delay_) + result.init_retry_delay_ = command_line_params.init_retry_delay_; + else if (client_factory_params.init_retry_delay_ != + result.init_retry_delay_) + result.init_retry_delay_ = client_factory_params.init_retry_delay_; + + // Retry on reply closed limit + if (command_line_params.forward_on_reply_closed_limit_ != + result.forward_on_reply_closed_limit_) + result.forward_on_reply_closed_limit_ = + command_line_params.forward_on_reply_closed_limit_; + else if (client_factory_params.forward_on_reply_closed_limit_ != + result.forward_on_reply_closed_limit_) + result.forward_on_reply_closed_limit_ = + client_factory_params.forward_on_reply_closed_limit_; + + // Forward on exception limits + + retry_limit_calc (TAO::FOE_OBJECT_NOT_EXIST, + command_line_params, + client_factory_params, + result); + + retry_limit_calc (TAO::FOE_COMM_FAILURE, + command_line_params, + client_factory_params, + result); + + retry_limit_calc (TAO::FOE_TRANSIENT, + command_line_params, + client_factory_params, + result); + + retry_limit_calc (TAO::FOE_INV_OBJREF, + command_line_params, + client_factory_params, + result); + + } + +} + +TAO::Invocation_Retry_State::Invocation_Retry_State (TAO_Stub &stub) + : forward_on_reply_closed_count_ (0) + , forward_on_exception_limit_used_ (false) +{ + this->ex_count_map_[FOE_OBJECT_NOT_EXIST] = 0; + this->ex_count_map_[FOE_COMM_FAILURE] = 0; + this->ex_count_map_[FOE_TRANSIENT] = 0; + this->ex_count_map_[FOE_INV_OBJREF] = 0; + + // Cast away const to avoid tedious iterator operations on the ACE_Array_Map. + TAO::Invocation_Retry_Params &command_line_params = + const_cast<TAO::Invocation_Retry_Params &> (stub.orb_core () + ->orb_params ()->invocation_retry_params ()); + TAO::Invocation_Retry_Params &client_factory_params = + const_cast<TAO::Invocation_Retry_Params &> (stub.orb_core () + ->client_factory ()->invocation_retry_params ()); + + retry_params_calc(command_line_params, + client_factory_params, + this->retry_params_); + + for (Invocation_Retry_Params::exception_limit_map_type::const_iterator i = + this->retry_params_.forward_on_exception_limit_.begin(); + i != this->retry_params_.forward_on_exception_limit_.end(); ++i) + { + if (i->second > 0) + { + forward_on_exception_limit_used_ = true; + break; + } + } +} + +TAO::Invocation_Retry_State::~Invocation_Retry_State () +{ +} + +bool +TAO::Invocation_Retry_State::forward_on_exception_limit_used () const +{ + return forward_on_exception_limit_used_; +} + +bool +TAO::Invocation_Retry_State::forward_on_exception_increment (const int ef) +{ + if (!this->forward_on_exception_limit_used_) + return false; + + int count = this->ex_count_map_[ef]; + Invocation_Retry_Params::exception_limit_map_type::const_iterator i = + this->retry_params_.forward_on_exception_limit_.find (ef); + int limit = i->second; + if (count < limit) + { + this->ex_count_map_[ef] = count + 1; + return true; + } + + return false; +} + +bool +TAO::Invocation_Retry_State::forward_on_reply_closed_increment () +{ + if (this->forward_on_reply_closed_count_ < + this->retry_params_.forward_on_reply_closed_limit_) + { + ++this->forward_on_reply_closed_count_; + return true; + } + + return false; +} + +void +TAO::Invocation_Retry_State::next_profile_retry (TAO_Stub &stub) const +{ + stub.next_profile_retry (); + this->sleep_at_starting_profile (stub); +} + +void +TAO::Invocation_Retry_State::sleep_at_starting_profile (TAO_Stub &stub) const +{ + if (stub.at_starting_profile ()) + this->sleep (); +} + +void +TAO::Invocation_Retry_State::sleep () const +{ + ACE_OS::sleep (this->retry_params_.init_retry_delay_); +} + + +TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/tao/Invocation_Retry_State.h b/TAO/tao/Invocation_Retry_State.h new file mode 100644 index 00000000000..096f32fadf8 --- /dev/null +++ b/TAO/tao/Invocation_Retry_State.h @@ -0,0 +1,98 @@ +/* -*- C++ -*- $Id$ */ +//============================================================================= +/** + * @file Invocation_Retry_State.h + * + * $Id$ + * + * @author Byron Harris (harrisb@ociweb.com) + * + */ +//============================================================================= + +#ifndef TAO_INVOCATION_RETRY_STATE_H +#define TAO_INVOCATION_RETRY_STATE_H + +#include "tao/Stub.h" +#include "tao/Invocation_Retry_Params.h" + +#include "ace/Array_Map.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +namespace TAO +{ + + /** + * @class Invocation_Retry_State + * + * @brief Maintains state of invocation retries. + */ + class Invocation_Retry_State + { + public: + Invocation_Retry_State (TAO_Stub &stub); + + ~Invocation_Retry_State (); + + /** + * Answer if any profile forward on exception limit + * parameter is used. + */ + bool forward_on_exception_limit_used () const; + + /** + * Attempt to increment the count of profile + * forwards. + * @return false if forward on exception is not + * being used or the limit has been reached. + */ + bool forward_on_exception_increment (const int ef); + + /** + * Attempt to increment the count of retries + * when a server connection is seen as closed + * during reply. + */ + bool forward_on_reply_closed_increment (); + + /** + * Increment to next profile in preparation + * to retry using that profile. + * If the next profile is the starting + * base profile then also call + * sleep (). + * @see TAO_Stub::next_profile_retry() + */ + void next_profile_retry (TAO_Stub &stub) const; + + /** + * Sleep if profile is the starting + * base profile. + */ + void sleep_at_starting_profile (TAO_Stub &stub) const; + + /** + * Sleep according to the delay value + * in Invocation_Retry_Params. + */ + void sleep () const; + + private: + + typedef ACE_Array_Map<int, int> Ex_Count_Map; + Ex_Count_Map ex_count_map_; + int forward_on_reply_closed_count_; + Invocation_Retry_Params retry_params_; + bool forward_on_exception_limit_used_; + }; + +} + +TAO_END_VERSIONED_NAMESPACE_DECL + +#endif /* TAO_INVOCATION_RETRY_STATE_H*/ diff --git a/TAO/tao/Invocation_Utils.h b/TAO/tao/Invocation_Utils.h index 54e8ec6a0c5..f17df10c510 100644 --- a/TAO/tao/Invocation_Utils.h +++ b/TAO/tao/Invocation_Utils.h @@ -71,7 +71,7 @@ namespace TAO TAO_DII_ASYNCH_INVOCATION }; - enum Forward_Once_Exception + enum Forward_On_Exception { FOE_NON = 0x0, FOE_OBJECT_NOT_EXIST = 0x1, diff --git a/TAO/tao/Messaging/Asynch_Invocation_Adapter.cpp b/TAO/tao/Messaging/Asynch_Invocation_Adapter.cpp index e0b8a583be7..3e189293220 100644 --- a/TAO/tao/Messaging/Asynch_Invocation_Adapter.cpp +++ b/TAO/tao/Messaging/Asynch_Invocation_Adapter.cpp @@ -152,8 +152,11 @@ namespace TAO TAO_Operation_Details &op, CORBA::Object_var &effective_target, Profile_Transport_Resolver &r, - ACE_Time_Value *&max_wait_time) + ACE_Time_Value *&max_wait_time, + Invocation_Retry_State *retry_state) { + ACE_UNUSED_ARG (retry_state); + // Simple sanity check if (this->mode_ != TAO_ASYNCHRONOUS_CALLBACK_INVOCATION || this->type_ != TAO_TWOWAY_INVOCATION) diff --git a/TAO/tao/Messaging/Asynch_Invocation_Adapter.h b/TAO/tao/Messaging/Asynch_Invocation_Adapter.h index 4c78afaedae..c562f2fcba8 100644 --- a/TAO/tao/Messaging/Asynch_Invocation_Adapter.h +++ b/TAO/tao/Messaging/Asynch_Invocation_Adapter.h @@ -80,7 +80,8 @@ namespace TAO TAO_Operation_Details &op, CORBA::Object_var &effective_target, Profile_Transport_Resolver &r, - ACE_Time_Value *&max_wait_time); + ACE_Time_Value *&max_wait_time, + Invocation_Retry_State *retry_state = 0); virtual Invocation_Status invoke_collocated_i ( TAO_Stub *stub, diff --git a/TAO/tao/ORB_Core.cpp b/TAO/tao/ORB_Core.cpp index 6fa0711bba6..cdae1455171 100644 --- a/TAO/tao/ORB_Core.cpp +++ b/TAO/tao/ORB_Core.cpp @@ -1102,7 +1102,54 @@ TAO_ORB_Core::init (int &argc, char *argv[] ) arg_shifter.consume_arg (); } else if (0 != (current_arg = arg_shifter.get_the_parameter - (ACE_TEXT("-ORBForwardOnceOnObjectNotExist")))) + (ACE_TEXT("-ORBForwardOnTransientLimit")))) + { + int limit = ACE_OS::atoi (current_arg); + this->orb_params_.forward_on_exception_limit (TAO::FOE_TRANSIENT, limit); + arg_shifter.consume_arg (); + } + else if (0 != (current_arg = arg_shifter.get_the_parameter + (ACE_TEXT("-ORBForwardOnCommFailureLimit")))) + { + int limit = ACE_OS::atoi (current_arg); + this->orb_params_.forward_on_exception_limit ( + TAO::FOE_COMM_FAILURE, limit); + arg_shifter.consume_arg (); + } + else if (0 != (current_arg = arg_shifter.get_the_parameter + (ACE_TEXT("-ORBForwardOnObjectNotExistLimit")))) + { + int limit = ACE_OS::atoi (current_arg); + this->orb_params_.forward_on_exception_limit ( + TAO::FOE_OBJECT_NOT_EXIST, limit); + arg_shifter.consume_arg (); + } + else if (0 != (current_arg = arg_shifter.get_the_parameter + (ACE_TEXT("-ORBForwardOnInvObjrefLimit")))) + { + int limit = ACE_OS::atoi (current_arg); + this->orb_params_.forward_on_exception_limit ( + TAO::FOE_INV_OBJREF, limit); + arg_shifter.consume_arg (); + } + else if (0 != (current_arg = arg_shifter.get_the_parameter + (ACE_TEXT("-ORBForwardOnReplyClosedLimit")))) + { + int limit = ACE_OS::atoi (current_arg); + this->orb_params_.invocation_retry_params () + .forward_on_reply_closed_limit_ = limit; + arg_shifter.consume_arg (); + } + else if (0 != (current_arg = arg_shifter.get_the_parameter + (ACE_TEXT("-ORBForwardDelay")))) + { + int msecs = ACE_OS::atoi (current_arg); + ACE_Time_Value delay(0, 1000*msecs); + this->orb_params_.forward_on_exception_delay (delay); + arg_shifter.consume_arg (); + } + else if (0 != (current_arg = arg_shifter.get_the_parameter + (ACE_TEXT("-ORBForwardOnceOnObjectNotExist")))) { int forward = ACE_OS::atoi (current_arg); if (forward) @@ -1138,12 +1185,18 @@ TAO_ORB_Core::init (int &argc, char *argv[] ) arg_shifter.consume_arg (); } else if (0 != (current_arg = arg_shifter.get_the_parameter - (ACE_TEXT("-ORBAllowZIOPNoServerPolicies")))) + (ACE_TEXT("-ORBAllowZIOPNoServerPolicies")))) { // This option takes a boolean 0 (off/dissallow) or 1 (on/allow) this->orb_params_.allow_ziop_no_server_policies (!!ACE_OS::atoi (current_arg)); arg_shifter.consume_arg (); } + else if (0 != (current_arg = arg_shifter.get_the_parameter + (ACE_TEXT("-ORBDynamicThreadPoolName")))) + { + this->orb_params_.dynamic_thread_pool_config_name (current_arg); + arg_shifter.consume_arg (); + } //////////////////////////////////////////////////////////////// // catch any unknown -ORB args // diff --git a/TAO/tao/PortableServer/ImR_Client_Adapter.h b/TAO/tao/PortableServer/ImR_Client_Adapter.h index 70be6e3c5d2..600aaa43fe6 100644 --- a/TAO/tao/PortableServer/ImR_Client_Adapter.h +++ b/TAO/tao/PortableServer/ImR_Client_Adapter.h @@ -29,8 +29,16 @@ TAO_BEGIN_VERSIONED_NAMESPACE_DECL class TAO_Root_POA; +namespace CORBA +{ + class Object; + typedef Object* Object_ptr; +} + namespace TAO { + class ObjectKey; + namespace Portable_Server { /** @@ -53,6 +61,13 @@ namespace TAO /// ImplRepo helper method, notify the ImplRepo on shutdown virtual void imr_notify_shutdown (TAO_Root_POA* poa ) = 0; + + /// ImplRepo helper method, create an IMR-ified object for a + /// key with a given type + virtual CORBA::Object_ptr imr_key_to_object( + TAO_Root_POA* poa, + const TAO::ObjectKey &key, + const char *type_id) const = 0; }; } } diff --git a/TAO/tao/PortableServer/LifespanStrategy.h b/TAO/tao/PortableServer/LifespanStrategy.h index 70e0c06c04d..7b562e8c801 100644 --- a/TAO/tao/PortableServer/LifespanStrategy.h +++ b/TAO/tao/PortableServer/LifespanStrategy.h @@ -37,9 +37,9 @@ namespace TAO public: LifespanStrategy (void); - virtual void strategy_init(TAO_Root_POA *poa); + virtual void strategy_init (TAO_Root_POA *poa); - virtual void strategy_cleanup(void); + virtual void strategy_cleanup (void); void create (const char *name, const TAO::ObjectKey &key); @@ -72,10 +72,14 @@ namespace TAO /// Check the state of the POA. virtual void check_state (void) = 0; - virtual ::PortableServer::LifespanPolicyValue type() const = 0; + virtual ::PortableServer::LifespanPolicyValue type () const = 0; virtual bool use_imr () const = 0; + virtual CORBA::Object_ptr imr_key_to_object ( + const TAO::ObjectKey &key, + const char *type_id) const = 0; + protected: TAO_Root_POA *poa_; }; diff --git a/TAO/tao/PortableServer/LifespanStrategyPersistent.cpp b/TAO/tao/PortableServer/LifespanStrategyPersistent.cpp index 093c7c5ef9e..0c82a670673 100644 --- a/TAO/tao/PortableServer/LifespanStrategyPersistent.cpp +++ b/TAO/tao/PortableServer/LifespanStrategyPersistent.cpp @@ -120,7 +120,7 @@ namespace TAO } } - LifespanStrategyPersistent::LifespanStrategyPersistent() : + LifespanStrategyPersistent::LifespanStrategyPersistent () : use_imr_ (true) { } @@ -142,6 +142,31 @@ namespace TAO { return use_imr_; } + + CORBA::Object_ptr + LifespanStrategyPersistent::imr_key_to_object (const TAO::ObjectKey &key, + const char *type_id) const + { + if (!this->use_imr_) + { + // not using the imr + return CORBA::Object::_nil (); + } + + // The user specified that the ImR should be used. + ImR_Client_Adapter *adapter = + ACE_Dynamic_Service<ImR_Client_Adapter>::instance ( + TAO_Root_POA::imr_client_adapter_name () + ); + if (adapter == 0) + { + // couldn't load adapter, already reported error + return CORBA::Object::_nil (); + } + + return adapter->imr_key_to_object (this->poa_, key, type_id); + } + } /* namespace Portable_Server */ } /* namespace TAO */ diff --git a/TAO/tao/PortableServer/LifespanStrategyPersistent.h b/TAO/tao/PortableServer/LifespanStrategyPersistent.h index ce8c9a7bdd6..d379607a91b 100644 --- a/TAO/tao/PortableServer/LifespanStrategyPersistent.h +++ b/TAO/tao/PortableServer/LifespanStrategyPersistent.h @@ -61,6 +61,9 @@ namespace TAO virtual bool use_imr () const; + virtual CORBA::Object_ptr imr_key_to_object(const TAO::ObjectKey &key, + const char *type_id) const; + private: bool use_imr_; }; diff --git a/TAO/tao/PortableServer/LifespanStrategyTransient.cpp b/TAO/tao/PortableServer/LifespanStrategyTransient.cpp index eec9ca12ce0..afe60a9b338 100644 --- a/TAO/tao/PortableServer/LifespanStrategyTransient.cpp +++ b/TAO/tao/PortableServer/LifespanStrategyTransient.cpp @@ -104,6 +104,13 @@ namespace TAO return false; } + CORBA::Object_ptr + LifespanStrategyTransient::imr_key_to_object (const TAO::ObjectKey &, + const char *) const + { + return CORBA::Object::_nil(); + } + ::PortableServer::LifespanPolicyValue LifespanStrategyTransient::type () const { diff --git a/TAO/tao/PortableServer/LifespanStrategyTransient.h b/TAO/tao/PortableServer/LifespanStrategyTransient.h index 46ebb3f5a15..2a811c485c1 100644 --- a/TAO/tao/PortableServer/LifespanStrategyTransient.h +++ b/TAO/tao/PortableServer/LifespanStrategyTransient.h @@ -58,6 +58,9 @@ namespace TAO virtual bool use_imr () const; + virtual CORBA::Object_ptr imr_key_to_object (const TAO::ObjectKey &key, + const char *type_id) const; + private: TAO::Portable_Server::Creation_Time creation_time_; }; diff --git a/TAO/tao/PortableServer/Root_POA.cpp b/TAO/tao/PortableServer/Root_POA.cpp index 3de8235bf06..497ed456c83 100644 --- a/TAO/tao/PortableServer/Root_POA.cpp +++ b/TAO/tao/PortableServer/Root_POA.cpp @@ -1948,77 +1948,16 @@ TAO_Root_POA::key_to_object (const TAO::ObjectKey &key, // #if (TAO_HAS_MINIMUM_CORBA == 0) - CORBA::Object_ptr obj = CORBA::Object::_nil (); - - if (indirect && this->active_policy_strategies_.lifespan_strategy()->use_imr () - && this->orb_core ().imr_endpoints_in_ior ()) + if (indirect && this->orb_core ().imr_endpoints_in_ior ()) { - // Check to see if we alter the IOR. - CORBA::Object_var imr = this->orb_core ().implrepo_service (); - - if (CORBA::is_nil (imr.in ()) - || !imr->_stubobj () - || !imr->_stubobj ()->profile_in_use ()) + CORBA::Object_ptr obj = this->active_policy_strategies_. + lifespan_strategy()->imr_key_to_object (key, type_id); + if (!CORBA::is_nil (obj)) { - if (TAO_debug_level > 1) - { - ACE_DEBUG ((LM_DEBUG, - "Missing ImR IOR, will not use the ImR\n")); - } - goto orbkey; + return obj; } - - CORBA::String_var imr_str = - imr->_stubobj ()->profile_in_use ()->to_string (); - - if (TAO_debug_level > 0) - ACE_DEBUG ((LM_DEBUG, - "IMR IOR =\n%C\n", - imr_str.in ())); - - // Search for "corbaloc:" alone, without the protocol. This code - // should be protocol neutral. - const char corbaloc[] = "corbaloc:"; - char *pos = ACE_OS::strstr (imr_str.inout (), corbaloc); - pos = ACE_OS::strchr (pos + sizeof (corbaloc), ':'); - - pos = ACE_OS::strchr (pos + 1, - imr->_stubobj ()->profile_in_use ()->object_key_delimiter ()); - - if (pos) - pos[1] = 0; // Crop the string. - else - { - if (TAO_debug_level > 0) - ACE_ERROR ((LM_ERROR, - "Could not parse ImR IOR, skipping ImRification\n")); - goto orbkey; - } - - ACE_CString ior (imr_str.in ()); - - // Add the key. - - CORBA::String_var key_str; - TAO::ObjectKey::encode_sequence_to_string (key_str.inout (), key); - - ior += key_str.in (); - - if (TAO_debug_level > 0) - ACE_DEBUG ((LM_DEBUG, - "ImR-ified IOR =\n%C\n", - ior.c_str ())); - - obj = this->orb_core_.orb ()->string_to_object (ior.c_str ()); - - // type_id info is not in the corbaloc, so set it here - obj->_stubobj()->type_id = type_id; - - return obj; } -orbkey: - #else ACE_UNUSED_ARG (indirect); #endif /* TAO_HAS_MINIMUM_CORBA */ diff --git a/TAO/tao/PortableServer/ServantRetentionStrategyNonRetain.cpp b/TAO/tao/PortableServer/ServantRetentionStrategyNonRetain.cpp index d797edb925e..de26ec8ee98 100644 --- a/TAO/tao/PortableServer/ServantRetentionStrategyNonRetain.cpp +++ b/TAO/tao/PortableServer/ServantRetentionStrategyNonRetain.cpp @@ -17,6 +17,10 @@ #include "tao/PortableServer/Servant_Base.h" #include "tao/debug.h" +#include "ace/OS_NS_sys_time.h" +#include "ace/Time_Value.h" +#include "ace/OS_NS_sys_time.h" + TAO_BEGIN_VERSIONED_NAMESPACE_DECL namespace TAO @@ -24,7 +28,8 @@ namespace TAO namespace Portable_Server { ServantRetentionStrategyNonRetain::ServantRetentionStrategyNonRetain (void) : - poa_ (0) + poa_ (0), + sys_id_count_ (0) { } @@ -188,12 +193,29 @@ namespace TAO PortableServer::ObjectId user_id; // Otherwise, it is the NON_RETAIN policy. Therefore, any ol' - // object id will do (even an empty one). + // object id will do (even an empty one). However, to make an + // object id useful for discriminating objects in applications + // use a simple id of a counter and a time stamp. The use of a + // counter by itself is not sufficient for uniqueness over time + // and a timestamp isn't sufficient since multiple IDs may be + // requested within the same time unit. + PortableServer::ObjectId *sys_id = 0; ACE_NEW_THROW_EX (sys_id, - PortableServer::ObjectId, + PortableServer::ObjectId (8), CORBA::NO_MEMORY ()); + sys_id->length(8); + + long count = this->sys_id_count_++; + ACE_Time_Value now = ACE_OS::gettimeofday(); + + *reinterpret_cast<ACE_UINT32 *>(sys_id->get_buffer()) = + count; + + *reinterpret_cast<ACE_UINT32 *>(sys_id->get_buffer() + 4) = + static_cast<ACE_UINT32>(now.sec()); + system_id = sys_id; // User id is the same as system id. diff --git a/TAO/tao/PortableServer/ServantRetentionStrategyNonRetain.h b/TAO/tao/PortableServer/ServantRetentionStrategyNonRetain.h index bc4a2e1d50b..6870c1e018c 100644 --- a/TAO/tao/PortableServer/ServantRetentionStrategyNonRetain.h +++ b/TAO/tao/PortableServer/ServantRetentionStrategyNonRetain.h @@ -21,6 +21,7 @@ #endif /* ACE_LACKS_PRAGMA_ONCE */ #include "tao/PortableServer/Servant_Location.h" +#include "ace/Atomic_Op.h" TAO_BEGIN_VERSIONED_NAMESPACE_DECL @@ -124,6 +125,7 @@ namespace TAO protected: TAO_Root_POA *poa_; + ACE_Atomic_Op<TAO_SYNCH_MUTEX,long> sys_id_count_; }; } } diff --git a/TAO/tao/Profile.cpp b/TAO/tao/Profile.cpp index 8cab33b26b8..4fdde3441a8 100644 --- a/TAO/tao/Profile.cpp +++ b/TAO/tao/Profile.cpp @@ -801,7 +801,7 @@ TAO_Unknown_Profile::object_key_delimiter (void) const } char * -TAO_Unknown_Profile::to_string (void) +TAO_Unknown_Profile::to_string (void) const { // @@ THROW something? return 0; diff --git a/TAO/tao/Profile.h b/TAO/tao/Profile.h index 6b5570c9481..34461840ee2 100644 --- a/TAO/tao/Profile.h +++ b/TAO/tao/Profile.h @@ -182,7 +182,7 @@ public: /// Return a string representation for this profile. Client must /// deallocate memory. Only one endpoint is included into the /// string. - virtual char* to_string (void) = 0; + virtual char* to_string (void) const = 0; /** * Encodes this profile's endpoints into a tagged component. @@ -430,7 +430,7 @@ public: // = The TAO_Profile methods look above virtual void parse_string (const char *string); virtual char object_key_delimiter (void) const; - virtual char* to_string (void); + virtual char* to_string (void) const; virtual int decode (TAO_InputCDR& cdr); virtual int encode (TAO_OutputCDR &stream) const; virtual int encode_endpoints (void); diff --git a/TAO/tao/Seq_Var_T.h b/TAO/tao/Seq_Var_T.h index 3ec1449d834..4d91492f547 100644 --- a/TAO/tao/Seq_Var_T.h +++ b/TAO/tao/Seq_Var_T.h @@ -61,8 +61,10 @@ public: _out_type out (void); _retn_type _retn (void); - /// TAO extension. - _retn_type ptr (void) const; + /// TAO extension. + _retn_type ptr (void) const; + operator T *& (); + protected: T * ptr_; }; @@ -120,9 +122,6 @@ public: T_elem operator[] (CORBA::ULong index); T_const_elem operator[] (CORBA::ULong index) const; - - /// Variable-size base types only. - operator T *& (); }; TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/tao/Seq_Var_T.inl b/TAO/tao/Seq_Var_T.inl index b1c7c16d024..ede406b652d 100644 --- a/TAO/tao/Seq_Var_T.inl +++ b/TAO/tao/Seq_Var_T.inl @@ -106,6 +106,13 @@ TAO_Seq_Var_Base_T<T>::ptr (void) const return this->ptr_; } +template<typename T> +ACE_INLINE +TAO_Seq_Var_Base_T<T>::operator T *& () +{ + return this->ptr_; +} + // *************************************************************** template<typename T> @@ -194,14 +201,6 @@ TAO_VarSeq_Var_T<T>::operator= (T * p) return *this; } -// Variable-size types only. -template<typename T> -ACE_INLINE -TAO_VarSeq_Var_T<T>::operator T *& () -{ - return this->ptr_; -} - template<typename T> ACE_INLINE typename TAO_VarSeq_Var_T<T>::T_elem diff --git a/TAO/tao/Storable_Base.cpp b/TAO/tao/Storable_Base.cpp new file mode 100644 index 00000000000..dc588dd8db8 --- /dev/null +++ b/TAO/tao/Storable_Base.cpp @@ -0,0 +1,97 @@ +//============================================================================= +/** + * @file Storable_Base.cpp + * + * $Id$ + * + * @author Bruce Trask <trask_b@ociweb.com> + * @author Chanaka Liyanaarachchi <chanaka@ociweb.com> + * @author Byron Harris <harrisb@ociweb.com> + */ +//============================================================================= + +#include "tao/Storable_Base.h" + +#if !defined (__ACE_INLINE__) +#include "tao/Storable_Base.inl" +#endif /* __ACE_INLINE__ */ + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +bool TAO::Storable_Base::use_backup_default = false; + +void +TAO::Storable_Base::remove (void) +{ + if (this->use_backup_) + { + this->remove_backup (); + } + this->do_remove (); +} + +bool +TAO::Storable_Base::use_backup () +{ + return this->use_backup_; +} + +ACE_CString +TAO::Storable_Base::state_as_string (Storable_State state) +{ + ACE_CString state_string; + if (state == goodbit) + state_string = "goodbit"; + else + { + if (state & badbit) + state_string = "badbit "; + if (state & eofbit) + state_string += "eofbit "; + if (state & failbit) + state_string += "failbit"; + } + return state_string; +} + +TAO::Storable_Exception:: +Storable_Exception (Storable_Base::Storable_State state, + const ACE_CString & file_name) + : storable_state_ (state) + , file_name_ (file_name) +{ +} + +TAO::Storable_Exception:: +~Storable_Exception () +{ +} + +TAO::Storable_Base::Storable_State +TAO::Storable_Exception::get_state () const +{ + return storable_state_; +} + +const ACE_CString & +TAO::Storable_Exception::get_file_name () const +{ + return file_name_; +} + +TAO::Storable_Read_Exception:: +Storable_Read_Exception (Storable_Base::Storable_State state, + const ACE_CString & file_name) + : Storable_Exception (state, file_name) +{ +} + +TAO::Storable_Write_Exception:: +Storable_Write_Exception (Storable_Base::Storable_State state, + const ACE_CString & file_name) + : Storable_Exception (state, file_name) +{ +} + + +TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/tao/Storable_Base.h b/TAO/tao/Storable_Base.h new file mode 100644 index 00000000000..b2fdcf7fc23 --- /dev/null +++ b/TAO/tao/Storable_Base.h @@ -0,0 +1,181 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file Storable_Base.h + * + * $Id$ + * + * @author Bruce Trask <trask_b@ociweb.com> + * @author Chanaka Liyanaarachchi <chanaka@ociweb.com> + * @author Byron Harris <harrisb@ociweb.com> + */ +//============================================================================= + +#ifndef TAO_STORABLE_BASE_H +#define TAO_STORABLE_BASE_H + +#include "tao/TAO_Export.h" +#include "tao/orbconf.h" +#include "tao/CDR.h" + +#include "ace/SString.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +#pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +namespace TAO +{ + + class TAO_Export Storable_Base + { + public: + + Storable_Base (bool use_backup); + + virtual ~Storable_Base (); + + /// The process-wide default policy + /// for doing a backup when close () + /// is called. + /// The backup can then be restored if + /// restore_backup () is called. + /// The initial value for the default is false. + static bool use_backup_default; + + bool use_backup (); + + /// Remove the file that is assumed to not be open. + /// If backup are used, the backup will also be removed. + void remove(); + + virtual int create_backup () = 0; + + virtual int exists() = 0; + + virtual int open () = 0; + + virtual int close () = 0; + + virtual int flock (int whence, int start, int len) = 0; + + virtual int funlock (int whence, int start, int len) = 0; + + virtual time_t last_changed(void) = 0; + + // Mimic a portion of the std::ios interface. We need to be able + // to indicate error states from the extraction operators below. + enum Storable_State { goodbit = 0, + badbit = 1, + eofbit = 2, + failbit = 4 + }; + + void clear (Storable_State state = goodbit); + + void setstate (Storable_State state); + + Storable_State rdstate (void) const; + + bool good (void) const; + + bool bad (void) const; + + bool eof (void) const; + + bool fail (void) const; + + static ACE_CString state_as_string (Storable_State state); + + virtual void rewind (void) = 0; + + virtual bool flush (void) = 0; + + /// Force write of storable data to storage. + /// Returns 0 on success, otherwise EOF + virtual int sync (void) = 0; + + virtual Storable_Base& operator << (const ACE_CString& str) = 0; + + virtual Storable_Base& operator >> (ACE_CString& str) = 0; + + virtual Storable_Base& operator << (int i) = 0; + + virtual Storable_Base& operator >> (int &i) = 0; + + virtual Storable_Base& operator << (unsigned int i) = 0; + + virtual Storable_Base& operator >> (unsigned int &i) = 0; + + virtual Storable_Base& operator << (const TAO_OutputCDR & cdr) = 0; + + virtual size_t write (size_t size, const char * bytes) = 0; + + virtual size_t read (size_t size, char * bytes) = 0; + + virtual int restore_backup () = 0; + + protected: + + virtual void do_remove () = 0; + + /// If a backup file exists, remove it. + virtual void remove_backup () = 0; + + bool use_backup_; + + private: + Storable_State state_; + + }; + + /// Base class for exceptions thrown when encountering + /// errors working with persistent files. + class TAO_Export Storable_Exception + { + public: + Storable_Exception (Storable_Base::Storable_State state, + const ACE_CString & file_name); + + virtual ~Storable_Exception (); + + Storable_Base::Storable_State get_state () const; + + const ACE_CString & get_file_name () const; + + private: + TAO::Storable_Base::Storable_State storable_state_; + ACE_CString file_name_; + }; + + /// Exception thrown when an error is encountered + /// during reading of the persistent store. + class TAO_Export Storable_Read_Exception : public Storable_Exception + { + public: + Storable_Read_Exception (Storable_Base::Storable_State state, + const ACE_CString & file_name); + }; + + /// Exception thrown when an error is encountered + /// during writing to the persistent store. + class TAO_Export Storable_Write_Exception : public Storable_Exception + { + public: + Storable_Write_Exception (Storable_Base::Storable_State state, + const ACE_CString & file_name); + }; + +} + +TAO_END_VERSIONED_NAMESPACE_DECL + +#if defined (__ACE_INLINE__) +#include "tao/Storable_Base.inl" +#endif + + +#endif diff --git a/TAO/tao/Storable_Base.inl b/TAO/tao/Storable_Base.inl new file mode 100644 index 00000000000..caddbdee3e7 --- /dev/null +++ b/TAO/tao/Storable_Base.inl @@ -0,0 +1,74 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file Storable_Base.inl + * + * $Id$ + * + * @author Bruce Trask <trask_b@ociweb.com> + * @author Chanaka Liyanaarachchi <chanaka@ociweb.com> + * @author Byron Harris <harrisb@ociweb.com> + */ +//============================================================================= + +#include "tao/Storable_Base.h" + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +ACE_INLINE +TAO::Storable_Base::Storable_Base (bool use_backup) + : use_backup_ (use_backup) + , state_ (goodbit) +{ +} + +ACE_INLINE +TAO::Storable_Base::~Storable_Base () +{ +} + +ACE_INLINE void +TAO::Storable_Base::clear (TAO::Storable_Base::Storable_State state) +{ + this->state_ = state; +} + +ACE_INLINE void +TAO::Storable_Base::setstate (TAO::Storable_Base::Storable_State state) +{ + this->clear (static_cast <TAO::Storable_Base::Storable_State> ( + this->rdstate () | state)); +} + +ACE_INLINE TAO::Storable_Base::Storable_State +TAO::Storable_Base::rdstate (void) const +{ + return this->state_; +} + +ACE_INLINE bool +TAO::Storable_Base::good (void) const +{ + return (this->state_ == goodbit); +} + +ACE_INLINE bool +TAO::Storable_Base::bad (void) const +{ + return (this->state_ & badbit); +} + +ACE_INLINE bool +TAO::Storable_Base::eof (void) const +{ + return (this->state_ & eofbit); +} + +ACE_INLINE bool +TAO::Storable_Base::fail (void) const +{ + return (this->state_ & failbit); +} + +TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/tao/Storable_Factory.cpp b/TAO/tao/Storable_Factory.cpp new file mode 100644 index 00000000000..8850ac57246 --- /dev/null +++ b/TAO/tao/Storable_Factory.cpp @@ -0,0 +1,25 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file Storable_Factory.cpp + * + * $Id$ + * + * @author Byron Harris <harrisb@ociweb.com> + */ +//============================================================================= + +#include "tao/Storable_Factory.h" + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +TAO::Storable_Factory::Storable_Factory (void) +{ +} + +TAO::Storable_Factory::~Storable_Factory (void) +{ +} + +TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/tao/Storable_Factory.h b/TAO/tao/Storable_Factory.h new file mode 100644 index 00000000000..2532c774254 --- /dev/null +++ b/TAO/tao/Storable_Factory.h @@ -0,0 +1,52 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file Storable_Factory.h + * + * $Id$ + * + * @author Byron Harris <harrisb@ociweb.com> + */ +//============================================================================= + +#ifndef TAO_STORABLE_FACTORY_H +#define TAO_STORABLE_FACTORY_H + +#include /**/ "ace/pre.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +#pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "tao/Storable_Base.h" + +#include "ace/SString.h" + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +namespace TAO +{ + + class TAO_Export Storable_Factory + { + public: + Storable_Factory(); + + virtual ~Storable_Factory(); + + // Factory Methods + + virtual Storable_Base *create_stream(const ACE_CString & file, + const ACE_TCHAR * mode, + bool use_backup = + Storable_Base::use_backup_default) = 0; + }; + +} + +TAO_END_VERSIONED_NAMESPACE_DECL + +#include /**/ "ace/post.h" + +#endif /* TAO_STORABLE_FACTORY_H */ diff --git a/TAO/tao/Storable_File_Guard.cpp b/TAO/tao/Storable_File_Guard.cpp new file mode 100644 index 00000000000..1c20d904df9 --- /dev/null +++ b/TAO/tao/Storable_File_Guard.cpp @@ -0,0 +1,266 @@ +//============================================================================= +/** + * @file Storable_File_Guard.cpp + * + * $Id$ + * + * @author Rich Seibel (seibelr@ociweb.com) + * @author Byron Harris (harrisb@ociweb.com) + */ +//============================================================================= + +#include "tao/Storable_File_Guard.h" +#include "tao/Storable_Base.h" + +#include "tao/SystemException.h" + +TAO::Storable_File_Guard:: +Storable_File_Guard (bool redundant, bool use_backup) + : redundant_(redundant) + , closed_(1) + , use_backup_(use_backup) +{ +} + +TAO::Storable_File_Guard:: +~Storable_File_Guard () +{ +} + +void +TAO::Storable_File_Guard::init(Method_Type method_type) +{ + + ACE_CString mode; + + // If backup is used then always need to open with + // write access since if the file is corrupt then + // will overwrite with backup file. + if (this->use_backup_) + { + switch (method_type) + { + case CREATE_WITH_FILE: + mode = "rw"; + break; + case CREATE_WITHOUT_FILE: + mode = "rwc"; + break; + case ACCESSOR: + mode = "rw"; + break; + case MUTATOR: + mode = "rw"; + break; + } + } + else + { + switch (method_type) + { + case CREATE_WITH_FILE: + mode = "r"; + break; + case CREATE_WITHOUT_FILE: + mode = "wc"; + break; + case ACCESSOR: + mode = "r"; + break; + case MUTATOR: + mode = "rw"; + break; + } + } + + // We only accept a subset of mode argument, check it + rwflags_ = 0; + for( unsigned int i = 0; i < mode.length (); i++ ) + { + switch (mode[i]) + { + case 'r': rwflags_ |= mode_read; + break; + case 'w': rwflags_ |= mode_write; + break; + case 'c': rwflags_ |= mode_create; + break; + default: rwflags_ = -1; + } + } + if( rwflags_ <= 0 ) + { + errno = EINVAL; + throw CORBA::PERSIST_STORE(); + } + + // Create the stream + fl_ = this->create_stream(mode.c_str ()); + if (redundant_) + { + if (fl_->open() != 0) + { + delete fl_; + throw CORBA::PERSIST_STORE(); + } + + // acquire a lock on it + if (fl_ -> flock(0, 0, 0) != 0) + { + fl_->close(); + delete fl_; + throw CORBA::INTERNAL(); + } + + // now that the file is successfully opened and locked it must be + // unlocked/closed before we leave this class + closed_ = 0; + + if ( ! (rwflags_ & mode_create) ) + { + // Check if our copy is up to date + if (this->object_obsolete ()) + { + this->mark_object_current (); + this->load (); + } + } + } + else if ( ! this->is_loaded_from_stream () || (rwflags_ & mode_write) ) + { + bool file_has_data = fl_->exists(); + + if (fl_->open() != 0) + { + delete fl_; + throw CORBA::PERSIST_STORE(); + } + + // now that the file is successfully opened + // unlocked/closed before we leave this class + closed_ = 0; + + if (file_has_data && ! this->is_loaded_from_stream ()) + { + this->load (); + } + } + else + { + // Need to insure that fl_ gets deleted + delete fl_; + } +} + +bool +TAO::Storable_File_Guard::object_obsolete (void) +{ // Default implementation uses time to determine + // if obsolete. + return (fl_->last_changed () > this->get_object_last_changed ()); +} + +void +TAO::Storable_File_Guard::mark_object_current (void) +{ // Default implementation is to set the last changed + // time to that of the file lock. + this->set_object_last_changed (fl_->last_changed ()); +} + +void +TAO::Storable_File_Guard::release (void) +{ + if ( ! closed_ ) + { + + if (this->use_backup_ ) + { + fl_->create_backup (); + } + + // If we updated the disk, save the time stamp + if(redundant_) + { + if( rwflags_ & mode_write ) + { + // This is a costly call, but necessary if + // we are running redundant. It ensures that + // the data is written to disk. + fl_->sync (); + + this->mark_object_current (); + } + + // Release the lock + fl_->funlock(0, 0, 0); + } + fl_->close(); + delete fl_; + closed_ = 1; + } + +} + +TAO::Storable_Base & +TAO::Storable_File_Guard::peer () +{ + return *fl_; +} + +void +TAO::Storable_File_Guard::load () +{ + if (!this->use_backup_) + { + this->load_from_stream (); + return; + } + + try + { + this->load_from_stream (); + } + catch (const Storable_Read_Exception &ex) + { + ACE_CString state_str = Storable_Base::state_as_string (ex.get_state()); + + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("TAO: (%P|%t) ERROR: State %s ") + ACE_TEXT ("encountered reading persistent ") + ACE_TEXT ("state from file\n%s\n"), + state_str.c_str (), ex.get_file_name().c_str ())); + + int result = this->fl_->restore_backup (); + + // result of 0 means OK. + if (!result) + { + + ACE_ERROR ((LM_INFO, + ACE_TEXT ("TAO: (%P|%t) Attempting to restore ") + ACE_TEXT ("from backup\n"))); + + try + { + this->load_from_stream (); + } + catch (const Storable_Read_Exception &ex) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("TAO: (%P|%t) ERROR: Unable to restore ") + ACE_TEXT ("the state from backup.\n"))); + throw; + } + ACE_ERROR ((LM_INFO, + ACE_TEXT ("TAO: (%P|%t) The state was restored ") + ACE_TEXT ("from backup.\n"))); + } + else + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("TAO: (%P|%t) ERROR: Could not read ") + ACE_TEXT ("backup file\n"))); + throw; + } + + } +} diff --git a/TAO/tao/Storable_File_Guard.h b/TAO/tao/Storable_File_Guard.h new file mode 100644 index 00000000000..6b4a055be38 --- /dev/null +++ b/TAO/tao/Storable_File_Guard.h @@ -0,0 +1,124 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file Storable_File_Guard.h + * + * $Id$ + * + * @author Rich Seibel (seibelr@ociweb.com) + * @author Byron Harris (harrisb@ociweb.com) + */ +//============================================================================= + +#ifndef TAO_STORABLE_FILE_GUARD_H +#define TAO_STORABLE_FILE_GUARD_H + +#include "tao/Storable_Base.h" + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +namespace TAO +{ + + /** + * @class Storable_File_Guard + * @brief Base class to use with TAO_Storable_Base to synch object state + * with a storable base. + * + * A guard for Storable_Base that opens a file + * for read/write and sets a lock on it. It then checks if the file has + * changed and re-reads it if it has. + * + */ + class TAO_Export Storable_File_Guard + { + public: + + Storable_File_Guard (bool redundant, + bool use_backup = Storable_Base::use_backup_default); + + virtual ~Storable_File_Guard (); + + /// Releases the lock, closes the file, and deletes the I/O stream. + /// Destructors of derived classes should call this this will + /// virtual functions are available. + void release (void); + + /// Return when the object in memory has last changed + virtual time_t get_object_last_changed () = 0; + + /// Get the underlying stream being used. + TAO::Storable_Base & peer (); + + /// Indicate how the state of the object is being used. + /// This is used for determine the mode for accessing + /// the persistent store. + enum Method_Type + { + + /// Construction with persistent file already existing + CREATE_WITH_FILE, + + /// Construction with persistent file not existing + CREATE_WITHOUT_FILE, + + /// Getting object state + ACCESSOR, + + /// Setting object state + MUTATOR + }; + + protected: + + /// Should be called by constructors of derived classes + /// since can't call the virtual functions below in constructor + /// of this class. + void init (Method_Type method_type); + + /// Check if the object is current with the last update. + virtual bool object_obsolete (void); + + /// Mark the object as up to date + virtual void mark_object_current (void); + + /// Indicate when the object in memory has last changed + virtual void set_object_last_changed (const time_t & time) = 0; + + /// Load object from file to memory + virtual void load_from_stream () = 0; + + /// Answer if object has been loaded from file + virtual bool is_loaded_from_stream () = 0; + + virtual Storable_Base * create_stream (const char * mode) = 0; + + /// The pointer to the actual file I/O (bridge pattern) + Storable_Base *fl_; + + private: + + void load (); + + bool redundant_; + + /// A flag to keep us from trying to close things more than once. + int closed_; + + /// The flags that we were opened with + int rwflags_; + + /// A flag indicating if backup/restore should be performed + bool use_backup_; + + /// Symbolic values for the flags in the above + enum { mode_write = 1, mode_read = 2, mode_create = 4 }; + + }; + +} + +TAO_END_VERSIONED_NAMESPACE_DECL + +#endif diff --git a/TAO/tao/Storable_FlatFileStream.cpp b/TAO/tao/Storable_FlatFileStream.cpp new file mode 100644 index 00000000000..3a5977c9dd8 --- /dev/null +++ b/TAO/tao/Storable_FlatFileStream.cpp @@ -0,0 +1,475 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file Storable_FlatFileStream.cpp + * + * $Id$ + * + * @author Marina Spivak <marina@cs.wustl.edu> + * @author Byron Harris <harrisb@ociweb.com> + */ +//============================================================================= + +#include "tao/Storable_FlatFileStream.h" + +#include "ace/OS_NS_unistd.h" +#include "ace/OS_NS_fcntl.h" +#include "ace/OS_NS_sys_stat.h" +#include "ace/Numeric_Limits.h" + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +namespace +{ + /// Avoids using fscanf to read an integer as any + /// whitespace following the newline will be + /// consumed. This could create problems if + /// the data that follows the newline is binary. + template<typename T> + void read_integer(const char * format, T & i, + TAO::Storable_Base::Storable_State & state, + FILE * fl) + { + char buf[BUFSIZ]; + char * result = fgets (buf, BUFSIZ, fl); + + if (result == 0) + { + if (feof (fl)) + { + state = TAO::Storable_Base::eofbit; + return; + } + state = TAO::Storable_Base::badbit; + return; + } + + /// Consume any starting newline, as fscanf would + /// do. + if (buf[0] == '\n') + { + result = fgets (buf, BUFSIZ, fl); + } + + if (result == 0) + { + if (feof (fl)) + { + state = TAO::Storable_Base::eofbit; + return; + } + state = TAO::Storable_Base::badbit; + return; + } + + switch (sscanf (buf, format, &i)) + { + case 0: + state = TAO::Storable_Base::badbit; + return; + case EOF: + state = TAO::Storable_Base::eofbit; + return; + } + } + + int file_copy(FILE *f1, FILE *f2) + { + char buffer[BUFSIZ]; + size_t n_read; + + bool all_read = false; + bool some_read = false; + + while (!all_read) + { + n_read = + ACE_OS::fread(buffer, 1, sizeof(buffer), f1); + if (n_read > 0) + { + if (ACE_OS::fwrite(buffer, 1, n_read, f2) != n_read) + return -1; + some_read = true; + } + else if (!some_read) + { + // Nothing was read + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("TAO: (%P|%t) ERROR: could not read from file\n"))); + + if (ferror (f1)) + { + ACE_ERROR ((LM_ERROR, + "%p\n", + "fread error")); + } + return -1; + } + else + { + all_read = true; + } + } + + return 0; + } + +} + +TAO::Storable_FlatFileStream::Storable_FlatFileStream (const ACE_CString & file, + const char * mode, + bool use_backup) + : Storable_Base(use_backup) + , fl_ (0) +{ + file_ = file; + mode_ = mode; +} + +TAO::Storable_FlatFileStream::~Storable_FlatFileStream () +{ + if ( fl_ != 0 ) + this->close(); +} + +void +TAO::Storable_FlatFileStream::do_remove () +{ + ACE_OS::unlink(ACE_TEXT_CHAR_TO_TCHAR(file_.c_str())); +} + +int +TAO::Storable_FlatFileStream::exists () +{ + // We could check the mode for this file, but for now just check exists + return ! ACE_OS::access(file_.c_str(), F_OK); +} + +int +TAO::Storable_FlatFileStream::open() +{ + // For now, three flags exist "r", "w", and "c" + int flags = 0; + const char *fdmode = 0; + if( ACE_OS::strchr(mode_.c_str(), 'r') ) + if( ACE_OS::strchr(mode_.c_str(), 'w') ) + flags = O_RDWR, fdmode = "w+"; + else + flags = O_RDONLY, fdmode = "r"; + else + flags = O_WRONLY, fdmode = "w"; + if( ACE_OS::strchr(mode_.c_str(), 'c') ) + flags |= O_CREAT; +#ifndef ACE_WIN32 + if( ACE_OS::flock_init (&filelock_, flags, ACE_TEXT_CHAR_TO_TCHAR(file_.c_str()), 0666) != 0 ) + ACE_ERROR_RETURN ((LM_ERROR, + "Cannot open file %s for mode %s: (%d) %s\n", + file_.c_str(), mode_.c_str(), + errno, ACE_OS::strerror(errno)), + -1); +#else + if( (filelock_.handle_= ACE_OS::open (ACE_TEXT_CHAR_TO_TCHAR(file_.c_str()), flags, 0)) == ACE_INVALID_HANDLE ) + ACE_ERROR_RETURN ((LM_ERROR, + "Cannot open file %s for mode %s: (%d) %s\n", + file_.c_str(), mode_.c_str(), + ACE_ERRNO_GET, ACE_OS::strerror(ACE_ERRNO_GET)), + -1); +#endif + this->fl_ = ACE_OS::fdopen(filelock_.handle_, ACE_TEXT_CHAR_TO_TCHAR(fdmode)); + if (this->fl_ == 0) + ACE_ERROR_RETURN ((LM_ERROR, + "Cannot fdopen file %s for mode %s: (%d) %s\n", + file_.c_str(), mode_.c_str(), + ACE_ERRNO_GET, ACE_OS::strerror(ACE_ERRNO_GET)), + -1); + return 0; +} + +int +TAO::Storable_FlatFileStream::close() +{ + ACE_OS::fflush(fl_); +#ifndef ACE_WIN32 + ACE_OS::flock_destroy (&filelock_, 0); +#endif + ACE_OS::fclose (fl_); // even though flock_destroy closes the handle + // we still need to destroy the FILE* + + fl_ = 0; + return 0; +} + +int +TAO::Storable_FlatFileStream::flock (int whence, int start, int len) +{ +#if defined (ACE_WIN32) + ACE_UNUSED_ARG (whence); + ACE_UNUSED_ARG (start); + ACE_UNUSED_ARG (len); +#else + if( ACE_OS::strcmp(mode_.c_str(), "r") == 0 ) + ACE_OS::flock_rdlock(&filelock_, whence, start, len); + else + ACE_OS::flock_wrlock(&filelock_, whence, start, len); +#endif + return 0; +} + +int +TAO::Storable_FlatFileStream::funlock (int whence, int start, int len) +{ +#if defined (ACE_WIN32) + ACE_UNUSED_ARG (whence); + ACE_UNUSED_ARG (start); + ACE_UNUSED_ARG (len); +#else + ACE_OS::flock_unlock(&filelock_, whence, start, len); +#endif + return 0; +} + +time_t +TAO::Storable_FlatFileStream::last_changed(void) +{ + ACE_stat st; + ACE_OS::fstat(filelock_.handle_, &st); + return st.st_mtime; +} + +void +TAO::Storable_FlatFileStream::rewind (void) +{ + return ACE_OS::rewind(this->fl_); +} + +bool +TAO::Storable_FlatFileStream::flush (void) +{ + return ACE_OS::fflush(this->fl_); +} + +int +TAO::Storable_FlatFileStream::sync (void) +{ + return ACE_OS::fsync (this->filelock_.handle_); +} + +TAO::Storable_Base & +TAO::Storable_FlatFileStream::operator << (const ACE_CString& str) +{ + int n = + ACE_OS::fprintf(this->fl_, ACE_SIZE_T_FORMAT_SPECIFIER ACE_TEXT("\n%s\n"), + str.length(), str.c_str()); + if (n < 0) + this->throw_on_write_error (badbit); + + return *this; +} + +TAO::Storable_Base & +TAO::Storable_FlatFileStream::operator >> (ACE_CString& str) +{ + int bufSize = 0; + ACE_CString::size_type const max_buf_len = + ACE_Numeric_Limits<ACE_CString::size_type>::max (); + switch (fscanf(fl_, "%d\n", &bufSize)) + { + case 0: + this->throw_on_read_error (badbit); + case EOF: + this->throw_on_read_error (eofbit); + } + + if (bufSize < 0 + || static_cast<ACE_CString::size_type> (bufSize) >= max_buf_len) + { + this->throw_on_read_error (badbit); + } + { + ACE_Auto_Basic_Array_Ptr<char> str_array (new char[bufSize + 1]); + str_array[0] = '\0'; + if (ACE_OS::fgets (ACE_TEXT_CHAR_TO_TCHAR (str_array.get ()), + bufSize + 1, + this->fl_) == 0 + && bufSize != 0) + { + this->throw_on_read_error (badbit); + } + str = ACE_CString (str_array.get (), 0, false); + } + + return *this; +} + +TAO::Storable_Base & +TAO::Storable_FlatFileStream::operator << (int i) +{ + int n = ACE_OS::fprintf (this->fl_, "%d\n", i); + if (n < 0) + this->throw_on_write_error (badbit); + return *this; +} + +TAO::Storable_Base & +TAO::Storable_FlatFileStream::operator >> (int &i) +{ + Storable_State state = this->rdstate (); + read_integer ("%d\n", i, state, fl_); + this->throw_on_read_error (state); + + return *this; +} + +TAO::Storable_Base & +TAO::Storable_FlatFileStream::operator << (unsigned int i) +{ + int n = ACE_OS::fprintf (this->fl_, "%u\n", i); + if (n < 0) + this->throw_on_write_error (badbit); + return *this; +} + +TAO::Storable_Base & +TAO::Storable_FlatFileStream::operator >> (unsigned int &i) +{ + Storable_State state = this->rdstate (); + read_integer ("%u\n", i, state, fl_); + this->throw_on_read_error (state); + + return *this; +} + +TAO::Storable_Base & +TAO::Storable_FlatFileStream::operator << (const TAO_OutputCDR & cdr) +{ + unsigned int length = cdr.total_length (); + *this << length; + for (const ACE_Message_Block *i = cdr.begin (); i != 0; i = i->cont ()) + { + const char *bytes = i->rd_ptr (); + size_t len = i->length (); + this->write (len, bytes); + } + return *this; +} + +size_t +TAO::Storable_FlatFileStream::write (size_t size, const char * bytes) +{ + return ACE_OS::fwrite (bytes, size, 1, fl_); +} + +size_t +TAO::Storable_FlatFileStream::read (size_t size, char * bytes) +{ + return ACE_OS::fread (bytes, size, 1, fl_); +} + +ACE_CString +TAO::Storable_FlatFileStream::backup_file_name () +{ + return file_ + ".bak"; +} + +int +TAO::Storable_FlatFileStream::create_backup () +{ + FILE * backup = ACE_OS::fopen (this->backup_file_name ().c_str (), "w"); + this->rewind(); + int result = file_copy(this->fl_, backup); + if (result != 0) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("TAO: (%P|%t) ERROR: Unable to create backup ") + ACE_TEXT ("of file\n%s\n"), file_.c_str ())); + } + ACE_OS::fclose (backup); + return result; +} + +void +TAO::Storable_FlatFileStream::remove_backup () +{ + ACE_CString backup_name = this->backup_file_name (); + + if (ACE_OS::access (ACE_TEXT_CHAR_TO_TCHAR (backup_name.c_str ()), F_OK) == 0) + { + ACE_OS::unlink (ACE_TEXT_CHAR_TO_TCHAR (backup_name.c_str ())); + } +} + +int +TAO::Storable_FlatFileStream::restore_backup () +{ + ACE_CString backup_name = this->backup_file_name ().c_str (); + + if (ACE_OS::access (ACE_TEXT_CHAR_TO_TCHAR (backup_name.c_str ()), F_OK)) + return -1; + + FILE * backup = ACE_OS::fopen (ACE_TEXT_CHAR_TO_TCHAR (backup_name.c_str ()), + "r"); + this->rewind(); + int result = file_copy(backup, this->fl_); + ACE_OS::fclose (backup); + this->flush (); + this->clear (); + return result; +} + +void +TAO::Storable_FlatFileStream::throw_on_read_error (Storable_State state) + throw (Storable_Read_Exception) +{ + this->setstate (state); + + if (!this->good ()) + { + throw Storable_Read_Exception (this->rdstate (), this->file_); + } +} + +void +TAO::Storable_FlatFileStream::throw_on_write_error (Storable_State state) + throw (Storable_Write_Exception) +{ + this->setstate (state); + + if (!this->good ()) + { + throw Storable_Write_Exception (this->rdstate (), this->file_); + } +} + +TAO::Storable_FlatFileFactory::Storable_FlatFileFactory(const ACE_CString & directory) + : Storable_Factory () + , directory_(directory) +{ +} + +TAO::Storable_FlatFileFactory::~Storable_FlatFileFactory() +{ +} + +const ACE_CString & +TAO::Storable_FlatFileFactory::get_directory () const +{ + return directory_; +} + +TAO::Storable_Base * +TAO::Storable_FlatFileFactory::create_stream (const ACE_CString & file, + const ACE_TCHAR * mode, + bool use_backup) +{ + TAO::Storable_Base *stream = 0; + ACE_CString path = this->directory_ + "/" + file; + ACE_NEW_RETURN (stream, + TAO::Storable_FlatFileStream(path, + ACE_TEXT_ALWAYS_CHAR (mode), + use_backup), + 0); + return stream; +} + +TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/tao/Storable_FlatFileStream.h b/TAO/tao/Storable_FlatFileStream.h new file mode 100644 index 00000000000..10e5a9e4425 --- /dev/null +++ b/TAO/tao/Storable_FlatFileStream.h @@ -0,0 +1,145 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file Storable_FlatFileStream.h + * + * $Id$ + * + * @author Marina Spivak <marina@cs.wustl.edu> + * @author Byron Harris <harrisb@ociweb.com> + */ +//============================================================================= + +#ifndef STORABLE_FLATFILESTREAM_H +#define STORABLE_FLATFILESTREAM_H + +#include /**/ "ace/pre.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +#pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "tao/Storable_Base.h" +#include "tao/Storable_Factory.h" +#include "ace/OS_NS_stdio.h" + +namespace TAO +{ + + /** + * @brief A Storable_Base derived class that works with a file stream. + * + */ + class TAO_Export Storable_FlatFileStream : public Storable_Base + { + public: + + Storable_FlatFileStream(const ACE_CString & file, const char * mode, + bool use_backup = + Storable_Base::use_backup_default); + + virtual ~Storable_FlatFileStream(); + + /// Check if a file exists on disk (file is not open) + virtual int exists (); + + /// Open a file (the remaining methods below all require an open file) + virtual int open (); + + /// Acquire a file lock + virtual int close (); + + /// Acquire a file lock + virtual int flock (int whence, int start, int len); + + /// Release a file lock + virtual int funlock (int whence, int start, int len); + + /// Returns the last time an open file was changed + virtual time_t last_changed (void); + + virtual void rewind (void); + + virtual bool flush (void); + + /// Force write of storable data to storage. + /// Returns 0 on success, otherwise EOF + virtual int sync (void); + + virtual Storable_Base& operator << (const ACE_CString& str); + + virtual Storable_Base& operator >> (ACE_CString& str); + + virtual Storable_Base& operator << (int i); + + virtual Storable_Base& operator >> (int &i); + + virtual Storable_Base& operator << (unsigned int i); + + virtual Storable_Base& operator >> (unsigned int &i); + + virtual Storable_Base& operator << (const TAO_OutputCDR & cdr); + + virtual size_t write (size_t size, const char * bytes); + + virtual size_t read (size_t size, char * bytes); + + virtual int restore_backup (); + + protected: + + virtual void do_remove (); + + virtual void remove_backup (); + + virtual int create_backup (); + + private: + + /// Throw a Storable_Read_Exception if the state + /// is not good due to a read error. + void throw_on_read_error (Storable_State state) + throw (Storable_Read_Exception); + + /// Throw a Storable_Write_Exception if the state + /// is not good due to a write error. + void throw_on_write_error (Storable_State state) + throw (Storable_Write_Exception); + + ACE_CString backup_file_name (); + + ACE_OS::ace_flock_t filelock_; + FILE* fl_; + ACE_CString file_; + ACE_CString mode_; + }; + + class TAO_Export Storable_FlatFileFactory : public Storable_Factory + { + public: + + /// @param directory Directory to contain file passed in + /// create_stream (). The directory is assumed to already exist. + Storable_FlatFileFactory(const ACE_CString & directory); + + const ACE_CString & get_directory () const; + + ~Storable_FlatFileFactory (); + + // Factory Methods + + /// Create the stream that can operate on a disk file + virtual Storable_Base *create_stream (const ACE_CString & file, + const ACE_TCHAR * mode, + bool use_backup = + Storable_Base::use_backup_default); + private: + ACE_CString directory_; + + }; +} + +#include /**/ "ace/post.h" + +#endif /* STORABLE_FLATFILESTREAM_H */ diff --git a/TAO/tao/Strategies/COIOP_Profile.cpp b/TAO/tao/Strategies/COIOP_Profile.cpp index ece1da6e39c..b2c075c2426 100644 --- a/TAO/tao/Strategies/COIOP_Profile.cpp +++ b/TAO/tao/Strategies/COIOP_Profile.cpp @@ -203,7 +203,7 @@ TAO_COIOP_Profile::add_endpoint (TAO_COIOP_Endpoint *endp) } char * -TAO_COIOP_Profile::to_string (void) +TAO_COIOP_Profile::to_string (void) const { CORBA::String_var key; TAO::ObjectKey::encode_sequence_to_string (key.inout(), diff --git a/TAO/tao/Strategies/COIOP_Profile.h b/TAO/tao/Strategies/COIOP_Profile.h index 075a2ccdbe5..ded0bf29f4d 100644 --- a/TAO/tao/Strategies/COIOP_Profile.h +++ b/TAO/tao/Strategies/COIOP_Profile.h @@ -65,7 +65,7 @@ public: ~TAO_COIOP_Profile (void); /// Template methods. Please tao/Profile.h for documentation. - virtual char * to_string (void); + virtual char * to_string (void) const; virtual int encode_endpoints (void); virtual TAO_Endpoint *endpoint (void); virtual CORBA::ULong endpoint_count (void) const; diff --git a/TAO/tao/Strategies/DIOP_Profile.cpp b/TAO/tao/Strategies/DIOP_Profile.cpp index b8b69911bab..2f5fc3c19b1 100644 --- a/TAO/tao/Strategies/DIOP_Profile.cpp +++ b/TAO/tao/Strategies/DIOP_Profile.cpp @@ -363,7 +363,7 @@ TAO_DIOP_Profile::add_endpoint (TAO_DIOP_Endpoint *endp) } char * -TAO_DIOP_Profile::to_string (void) +TAO_DIOP_Profile::to_string (void) const { // corbaloc:diop:1.2@host:port,diop:1.2@host:port,.../key diff --git a/TAO/tao/Strategies/DIOP_Profile.h b/TAO/tao/Strategies/DIOP_Profile.h index f2db5d68c01..5b4725c0418 100644 --- a/TAO/tao/Strategies/DIOP_Profile.h +++ b/TAO/tao/Strategies/DIOP_Profile.h @@ -77,7 +77,7 @@ public: /// Template methods. Please tao/Profile.h for documentation. - virtual char * to_string (void); + virtual char * to_string (void) const; virtual int encode_endpoints (void); virtual TAO_Endpoint *endpoint (void); virtual CORBA::ULong endpoint_count (void) const; diff --git a/TAO/tao/Strategies/SCIOP_Profile.cpp b/TAO/tao/Strategies/SCIOP_Profile.cpp index 175fbe7bfd9..83899b63a7e 100644 --- a/TAO/tao/Strategies/SCIOP_Profile.cpp +++ b/TAO/tao/Strategies/SCIOP_Profile.cpp @@ -310,7 +310,7 @@ TAO_SCIOP_Profile::add_endpoint (TAO_SCIOP_Endpoint *endp) } char * -TAO_SCIOP_Profile::to_string (void) +TAO_SCIOP_Profile::to_string (void) const { CORBA::String_var key; TAO::ObjectKey::encode_sequence_to_string (key.inout(), diff --git a/TAO/tao/Strategies/SCIOP_Profile.h b/TAO/tao/Strategies/SCIOP_Profile.h index 4aca872c3d7..264edc4cf57 100644 --- a/TAO/tao/Strategies/SCIOP_Profile.h +++ b/TAO/tao/Strategies/SCIOP_Profile.h @@ -73,7 +73,7 @@ public: ~TAO_SCIOP_Profile (void); /// Template methods. Please see Profile.h for documentation. - virtual char * to_string (void); + virtual char * to_string (void) const; virtual int encode_endpoints (void); virtual TAO_Endpoint *endpoint (void); virtual CORBA::ULong endpoint_count (void) const; diff --git a/TAO/tao/Strategies/SHMIOP_Profile.cpp b/TAO/tao/Strategies/SHMIOP_Profile.cpp index 23f7c52818e..e13b03ac3c3 100644 --- a/TAO/tao/Strategies/SHMIOP_Profile.cpp +++ b/TAO/tao/Strategies/SHMIOP_Profile.cpp @@ -325,7 +325,7 @@ TAO_SHMIOP_Profile::add_endpoint (TAO_SHMIOP_Endpoint *endp) } char * -TAO_SHMIOP_Profile::to_string (void) +TAO_SHMIOP_Profile::to_string (void) const { CORBA::String_var key; TAO::ObjectKey::encode_sequence_to_string (key.inout(), diff --git a/TAO/tao/Strategies/SHMIOP_Profile.h b/TAO/tao/Strategies/SHMIOP_Profile.h index 7d103435dc2..49689fb03bb 100644 --- a/TAO/tao/Strategies/SHMIOP_Profile.h +++ b/TAO/tao/Strategies/SHMIOP_Profile.h @@ -76,7 +76,7 @@ public: /// Template methods, please see Profile.h for documentation. - virtual char * to_string (void); + virtual char * to_string (void) const; virtual int encode_endpoints (void); virtual TAO_Endpoint *endpoint (void); virtual CORBA::ULong endpoint_count (void) const; diff --git a/TAO/tao/Strategies/UIOP_Profile.cpp b/TAO/tao/Strategies/UIOP_Profile.cpp index 8cf254c9d6b..e74fcd28d0b 100644 --- a/TAO/tao/Strategies/UIOP_Profile.cpp +++ b/TAO/tao/Strategies/UIOP_Profile.cpp @@ -239,7 +239,7 @@ TAO_UIOP_Profile::add_endpoint (TAO_UIOP_Endpoint *endp) char * -TAO_UIOP_Profile::to_string (void) +TAO_UIOP_Profile::to_string (void) const { CORBA::String_var key; TAO::ObjectKey::encode_sequence_to_string (key.inout(), diff --git a/TAO/tao/Strategies/UIOP_Profile.h b/TAO/tao/Strategies/UIOP_Profile.h index 8870fcec6e5..eb4b146989d 100644 --- a/TAO/tao/Strategies/UIOP_Profile.h +++ b/TAO/tao/Strategies/UIOP_Profile.h @@ -75,7 +75,7 @@ public: ~TAO_UIOP_Profile (void); /// Template methods. Please see Profile.h for documentation. - virtual char *to_string (void); + virtual char *to_string (void) const; virtual int encode_endpoints (void); virtual TAO_Endpoint *endpoint (void); virtual CORBA::ULong endpoint_count (void) const; diff --git a/TAO/tao/Stub.cpp b/TAO/tao/Stub.cpp index 0703795d5d4..b6bdbeaea36 100644 --- a/TAO/tao/Stub.cpp +++ b/TAO/tao/Stub.cpp @@ -116,6 +116,13 @@ TAO_Stub::add_forward_profiles (const TAO_MProfile &mprofiles, ACE_MT (ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->profile_lock_)); + if (TAO_debug_level > 5) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - Stub::add_forward_profiles, ") + ACE_TEXT ("acquired profile lock this = 0x%x\n"), + this)); + } if (permanent_forward) { @@ -133,8 +140,10 @@ TAO_Stub::add_forward_profiles (const TAO_MProfile &mprofiles, TAO_MProfile (mprofiles)); if (permanent_forward) - // bookmark the new element at bottom of stack - this->forward_profiles_perm_ = this->forward_profiles_; + { + // bookmark the new element at bottom of stack + this->forward_profiles_perm_ = this->forward_profiles_; + } // forwarded profile points to the new IOR (profiles) this->profile_in_use_->forward_to (this->forward_profiles_); @@ -159,6 +168,14 @@ TAO_Stub::create_ior_info (IOP::IOR *&ior_info, CORBA::ULong &index) guard, this->profile_lock_, -1)); + if (TAO_debug_level > 5) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - Stub::create_ior_info, acquired ") + ACE_TEXT ("profile lock this = 0x%x\n"), + this)); + } + IOP::IOR *tmp_info = 0; @@ -223,7 +240,8 @@ TAO_Stub::object_key (void) const { // Double-checked // FUZZ: disable check_for_ACE_Guard - ACE_Guard<TAO_SYNCH_MUTEX> obj (const_cast <TAO_SYNCH_MUTEX&>(this->profile_lock_)); + ACE_Guard<TAO_SYNCH_MUTEX> obj ( + const_cast <TAO_SYNCH_MUTEX&>(this->profile_lock_)); // FUZZ: enable check_for_ACE_Guard if (obj.locked () != 0 && this->forward_profiles_ != 0) @@ -520,6 +538,14 @@ TAO_Stub::marshal (TAO_OutputCDR &cdr) guard, this->profile_lock_, 0)); + if (TAO_debug_level > 5) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - Stub::marshal, acquired ") + ACE_TEXT ("profile lock this = 0x%x\n"), + this)); + } + ACE_ASSERT(this->forward_profiles_ !=0); diff --git a/TAO/tao/Stub.h b/TAO/tao/Stub.h index 789bc8e2e9b..a654e3931de 100644 --- a/TAO/tao/Stub.h +++ b/TAO/tao/Stub.h @@ -165,6 +165,11 @@ public: */ void reset_profiles (void); + /// Returns true if the profile in use is + /// the same as the profile in use after + /// reset_profiles() is called. + CORBA::Boolean at_starting_profile (void) const; + /// Returns true if a forward profile has successfully been used. /// profile_success_ && forward_profiles_ CORBA::Boolean valid_forward_profile (void); @@ -406,6 +411,7 @@ protected: /// True if forwarding request upon some specific exceptions /// (e.g. OBJECT_NOT_EXIST) already happened. ACE_Atomic_Op<TAO_SYNCH_MUTEX, bool> forwarded_on_exception_; + }; // Define a TAO_Stub auto_ptr class. diff --git a/TAO/tao/Stub.inl b/TAO/tao/Stub.inl index d4b0ae3d8c7..714d1d736b2 100644 --- a/TAO/tao/Stub.inl +++ b/TAO/tao/Stub.inl @@ -3,6 +3,7 @@ // $Id$ #include "tao/ORB_Core.h" +#include "ace/Reverse_Lock_T.h" TAO_BEGIN_VERSIONED_NAMESPACE_DECL @@ -56,6 +57,14 @@ TAO_Stub::reset_profiles (void) ACE_MT (ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->profile_lock_)); + if (TAO_debug_level > 5) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - Stub::reset_profiles, acquired ") + ACE_TEXT ("profile lock this = 0x%x\n"), + this)); + } + this->reset_profiles_i (); } @@ -137,9 +146,30 @@ TAO_Stub::next_profile_i (void) pfile_next = this->base_profiles_.get_next (); } - // We may have been forwarded to / from a collocated situation - // Check for this and apply / remove optimisation if required. - this->orb_core_->reinitialize_object (this); + { + typedef ACE_Reverse_Lock<ACE_MT_SYNCH::MUTEX> TAO_REVERSE_LOCK; + TAO_REVERSE_LOCK reverse (this->profile_lock_); + ACE_MT (ACE_GUARD_RETURN (TAO_REVERSE_LOCK, ace_mon, reverse, 0)); + if (TAO_debug_level > 5) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - Stub::next_profile_i, ") + ACE_TEXT ("released profile lock to reinitialize ") + ACE_TEXT ("this = 0x%x\n"), + this)); + } + // We may have been forwarded to / from a collocated situation + // Check for this and apply / remove optimisation if required. + this->orb_core_->reinitialize_object (this); + } + if (TAO_debug_level > 5) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - Stub::next_profile_i, ") + ACE_TEXT ("reacquired profile lock on object ") + ACE_TEXT ("this = 0x%x\n"), + this)); + } } else pfile_next = this->base_profiles_.get_next (); @@ -160,6 +190,11 @@ TAO_Stub::next_profile (void) guard, this->profile_lock_, 0)); + if (TAO_debug_level > 5) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - Stub::next_profile, acquired profile lock this = 0x%x\n"), this)); + } return this->next_profile_i (); } @@ -188,6 +223,12 @@ TAO_Stub::base_profiles (const TAO_MProfile &mprofiles) guard, this->profile_lock_, 0)); + if (TAO_debug_level > 5) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - Stub::base_profiles, acquired profile lock this = 0x%x\n"), this)); + } + // first reset things so we start from scratch! @@ -208,6 +249,11 @@ TAO_Stub::next_profile_retry (void) guard, this->profile_lock_, 0)); + if (TAO_debug_level > 5) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - Stub::next_profile_retry, acquired profile lock this = 0x%x\n"), this)); + } if (this->profile_success_ && this->forward_profiles_) { @@ -362,6 +408,13 @@ TAO_Stub::_decr_refcnt (void) delete this; } +ACE_INLINE +CORBA::Boolean +TAO_Stub::at_starting_profile (void) const +{ + return profile_in_use_ == base_profiles_.get_profile(0); +} + // --------------------------------------------------------------- // Creator methods for TAO_Stub_Auto_Ptr (TAO_Stub Auto Pointer) diff --git a/TAO/tao/Synch_Invocation.cpp b/TAO/tao/Synch_Invocation.cpp index 40064362ca6..71ef977e300 100644 --- a/TAO/tao/Synch_Invocation.cpp +++ b/TAO/tao/Synch_Invocation.cpp @@ -1,6 +1,7 @@ // $Id$ #include "tao/Synch_Invocation.h" +#include "tao/Invocation_Retry_State.h" #include "tao/Profile_Transport_Resolver.h" #include "tao/Profile.h" #include "tao/Synch_Reply_Dispatcher.h" @@ -42,9 +43,16 @@ namespace TAO resolver, detail, response_expected) + , retry_state_ (0) { } + void + Synch_Twoway_Invocation::set_retry_state (Invocation_Retry_State *retry_state) + { + this->retry_state_ = retry_state; + } + Invocation_Status Synch_Twoway_Invocation::remote_twoway (ACE_Time_Value *max_wait_time) { @@ -79,10 +87,25 @@ namespace TAO if (!transport) { - // Way back, we failed to find a profile we could connect to. - // We've come this far only so we reach the interception points - // in case they can fix things. Time to bail.... - throw CORBA::TRANSIENT (CORBA::OMGVMCID | 2, CORBA::COMPLETED_NO); + if (this->retry_state_ && + this->retry_state_->forward_on_exception_increment(FOE_TRANSIENT)) + { + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_INFO, + ACE_TEXT ("TAO (%P|%t) - Synch_Twoway_Invocation::") + ACE_TEXT ("remote_twoway retrying on TRANSIENT ") + ACE_TEXT ("exception\n"))); + this->retry_state_->next_profile_retry (*this->stub ()); + return TAO_INVOKE_RESTART; + } + else + { + // Way back, we failed to find a profile we could connect to. + // We've come this far only so we reach the interception points + // in case they can fix things. Time to bail.... + throw CORBA::TRANSIENT (CORBA::OMGVMCID | 2, CORBA::COMPLETED_NO); + } + } ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, ace_mon, @@ -259,8 +282,8 @@ namespace TAO if (TAO_debug_level > 0 && max_wait_time) { ACE_DEBUG ((LM_DEBUG, - "TAO (%P|%t) - Synch_Twoway_Invocation::wait_for_reply, " - "timeout after recv is <%u> status <%d>\n", + ACE_TEXT ("TAO (%P|%t) - Synch_Twoway_Invocation::wait_for_reply, ") + ACE_TEXT ("timeout after recv is <%u> status <%d>\n"), max_wait_time->msec (), reply_error)); } @@ -273,8 +296,9 @@ namespace TAO if (TAO_debug_level > 3) { ACE_DEBUG ((LM_DEBUG, - "TAO (%P|%t) - Synch_Twoway_Invocation::wait_for_reply, " - "recovering after an error\n")); + ACE_TEXT ("TAO (%P|%t) - Synch_Twoway_Invocation::") + ACE_TEXT ("wait_for_reply, ") + ACE_TEXT ("recovering after an error\n"))); } // You the smarty, don't try to moving the unbind_dispatcher @@ -312,6 +336,19 @@ namespace TAO (void) bd.unbind_dispatcher (); this->resolver_.transport ()->close_connection (); + if (this->retry_state_ && + this->resolver_.transport ()->connection_closed_on_read() && + this->retry_state_->forward_on_reply_closed_increment ()) + { + if (TAO_debug_level > 4) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - Synch_Twoway_Invocation::") + ACE_TEXT ("wait_for_reply, forward profile on ") + ACE_TEXT ("connection closed\n"))); + this->retry_state_->next_profile_retry (*this->stub ()); + return TAO_INVOKE_RESTART; + } + try { return @@ -322,7 +359,11 @@ namespace TAO } catch (const ::CORBA::Exception&) { - this->resolver_.stub ()->reset_profiles (); + if (this->retry_state_ == 0 || + !this->retry_state_->forward_on_exception_limit_used ()) + { + this->resolver_.stub ()->reset_profiles (); + } throw; } } @@ -386,8 +427,9 @@ namespace TAO // permanent condition not given if (TAO_debug_level > 3) ACE_DEBUG ((LM_DEBUG, - "TAO (%P|%t) - Synch_Twoway_Invocation::" - "check_reply_status: unexpected LOCATION_FORWARD_PERM reply\n")); + ACE_TEXT ("TAO (%P|%t) - Synch_Twoway_Invocation::") + ACE_TEXT ("check_reply_status: unexpected ") + ACE_TEXT ("LOCATION_FORWARD_PERM reply\n"))); throw ::CORBA::INTERNAL (0, CORBA::COMPLETED_NO); } @@ -439,8 +481,8 @@ namespace TAO if (TAO_debug_level > 3) { ACE_DEBUG ((LM_DEBUG, - ACE_TEXT ("TAO (%P|%t) - Synch_Twoway_Invocation::location_forward ") - ACE_TEXT ("being handled\n"))); + ACE_TEXT ("TAO (%P|%t) - Synch_Twoway_Invocation::") + ACE_TEXT ("location_forward being handled\n"))); } CORBA::Object_var fwd; @@ -469,8 +511,8 @@ namespace TAO if (TAO_debug_level > 3) ACE_DEBUG ((LM_DEBUG, - "TAO (%P|%t) - Synch_Twoway_Invocation::" - "handle_user_exception\n")); + ACE_TEXT ("TAO (%P|%t) - Synch_Twoway_Invocation::") + ACE_TEXT ("handle_user_exception\n"))); // Pull the exception from the stream. CORBA::String_var buf; @@ -513,8 +555,8 @@ namespace TAO if (TAO_debug_level > 3) ACE_DEBUG ((LM_DEBUG, - "TAO (%P|%t) - Synch_Twoway_Invocation::" - "handle_system_exception\n")); + ACE_TEXT ("TAO (%P|%t) - Synch_Twoway_Invocation::") + ACE_TEXT ("handle_system_exception\n"))); CORBA::String_var type_id; @@ -533,40 +575,80 @@ namespace TAO throw ::CORBA::MARSHAL (0, CORBA::COMPLETED_MAYBE); } + bool retry_on_exception = false; bool do_forward = false; - int foe_kind = this->stub ()->orb_core ()->orb_params ()->forward_once_exception(); - - if ((CORBA::CompletionStatus) completion != CORBA::COMPLETED_YES - && (((foe_kind & TAO::FOE_TRANSIENT) == 0 - && ACE_OS_String::strcmp (type_id.in (), - "IDL:omg.org/CORBA/TRANSIENT:1.0") == 0) || - ACE_OS_String::strcmp (type_id.in (), - "IDL:omg.org/CORBA/OBJ_ADAPTER:1.0") == 0 || - ACE_OS_String::strcmp (type_id.in (), - "IDL:omg.org/CORBA/NO_RESPONSE:1.0") == 0 || - ((foe_kind & TAO::FOE_COMM_FAILURE) == 0 - && ACE_OS_String::strcmp (type_id.in (), - "IDL:omg.org/CORBA/COMM_FAILURE:1.0") == 0) || - (this->stub ()->orb_core ()->orb_params ()->forward_invocation_on_object_not_exist () - && ACE_OS_String::strcmp (type_id.in (), - "IDL:omg.org/CORBA/OBJECT_NOT_EXIST:1.0") == 0) || - (do_forward = ! this->stub ()->forwarded_on_exception () - && ((((foe_kind & TAO::FOE_OBJECT_NOT_EXIST) == TAO::FOE_OBJECT_NOT_EXIST) - && (ACE_OS_String::strcmp (type_id.in (), - "IDL:omg.org/CORBA/OBJECT_NOT_EXIST:1.0") == 0)) || - (((foe_kind & TAO::FOE_COMM_FAILURE) == TAO::FOE_COMM_FAILURE) - && (ACE_OS_String::strcmp (type_id.in (), - "IDL:omg.org/CORBA/COMM_FAILURE:1.0") == 0)) || - (((foe_kind & TAO::FOE_TRANSIENT) == TAO::FOE_TRANSIENT) - && (ACE_OS_String::strcmp (type_id.in (), - "IDL:omg.org/CORBA/TRANSIENT:1.0") == 0)) || - (((foe_kind & TAO::FOE_INV_OBJREF) == TAO::FOE_INV_OBJREF) - && (ACE_OS_String::strcmp (type_id.in (), - "IDL:omg.org/CORBA/INV_OBJREF:1.0") == 0)))))) + + const TAO_ORB_Parameters *orb_params = this->stub ()->orb_core ()->orb_params (); + + if (this->retry_state_ && + this->retry_state_->forward_on_exception_limit_used () && + (CORBA::CompletionStatus) completion == CORBA::COMPLETED_NO) + { + if ((ACE_OS_String::strcmp (type_id.in (), + "IDL:omg.org/CORBA/TRANSIENT:1.0") == 0 && + this->retry_state_->forward_on_exception_increment (TAO::FOE_TRANSIENT)) || + (ACE_OS_String::strcmp (type_id.in (), + "IDL:omg.org/CORBA/COMM_FAILURE:1.0") == 0 && + this->retry_state_->forward_on_exception_increment (TAO::FOE_COMM_FAILURE)) || + (ACE_OS_String::strcmp (type_id.in (), + "IDL:omg.org/CORBA/OBJECT_NOT_EXIST:1.0") == 0 && + this->retry_state_->forward_on_exception_increment (TAO::FOE_OBJECT_NOT_EXIST)) || + (ACE_OS_String::strcmp (type_id.in (), + "IDL:omg.org/CORBA/INV_OBJREF:1.0") == 0 && + this->retry_state_->forward_on_exception_increment (TAO::FOE_INV_OBJREF)) + ) + { + retry_on_exception = true; + this->retry_state_->sleep_at_starting_profile (*this->stub ()); + } + } + else + { + int foe_kind = orb_params->forward_once_exception(); + + retry_on_exception = + (CORBA::CompletionStatus) completion != CORBA::COMPLETED_YES + && (((foe_kind & TAO::FOE_TRANSIENT) == 0 + && ACE_OS_String::strcmp (type_id.in (), + "IDL:omg.org/CORBA/TRANSIENT:1.0") == 0) || + ACE_OS_String::strcmp (type_id.in (), + "IDL:omg.org/CORBA/OBJ_ADAPTER:1.0") == 0 || + ACE_OS_String::strcmp (type_id.in (), + "IDL:omg.org/CORBA/NO_RESPONSE:1.0") == 0 || + ((foe_kind & TAO::FOE_COMM_FAILURE) == 0 + && ACE_OS_String::strcmp (type_id.in (), + "IDL:omg.org/CORBA/COMM_FAILURE:1.0") == 0) || + (orb_params->forward_invocation_on_object_not_exist () + && ACE_OS_String::strcmp (type_id.in (), + "IDL:omg.org/CORBA/OBJECT_NOT_EXIST:1.0") == 0) || + (do_forward = ! this->stub ()->forwarded_on_exception () + && ((((foe_kind & TAO::FOE_OBJECT_NOT_EXIST) == TAO::FOE_OBJECT_NOT_EXIST) + && (ACE_OS_String::strcmp (type_id.in (), + "IDL:omg.org/CORBA/OBJECT_NOT_EXIST:1.0") == 0)) || + (((foe_kind & TAO::FOE_COMM_FAILURE) == TAO::FOE_COMM_FAILURE) + && (ACE_OS_String::strcmp (type_id.in (), + "IDL:omg.org/CORBA/COMM_FAILURE:1.0") == 0)) || + (((foe_kind & TAO::FOE_TRANSIENT) == TAO::FOE_TRANSIENT) + && (ACE_OS_String::strcmp (type_id.in (), + "IDL:omg.org/CORBA/TRANSIENT:1.0") == 0)) || + (((foe_kind & TAO::FOE_INV_OBJREF) == TAO::FOE_INV_OBJREF) + && (ACE_OS_String::strcmp (type_id.in (), + "IDL:omg.org/CORBA/INV_OBJREF:1.0") == 0))))); + } + + if (retry_on_exception) { // If we are here then possibly we'll need a restart. mon.set_status (TAO_INVOKE_RESTART); + if (TAO_debug_level > 4) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - Synch_Twoway_Invocation::") + ACE_TEXT ("handle_system_exception, profile forwarding ") + ACE_TEXT ("on exception "), + type_id.in (), + ACE_TEXT ("\n"))); + if (do_forward) this->stub ()->forwarded_on_exception (true); @@ -625,8 +707,8 @@ namespace TAO if (TAO_debug_level > 4) ACE_DEBUG ((LM_DEBUG, - "TAO (%P|%t) - Synch_Twoway_Invocation::" - "handle_system_exception, about to raise\n")); + ACE_TEXT ("TAO (%P|%t) - Synch_Twoway_Invocation::") + ACE_TEXT ("handle_system_exception, about to raise\n"))); mon.set_status (TAO_INVOKE_SYSTEM_EXCEPTION); @@ -676,80 +758,98 @@ namespace TAO if (!transport) { - // Way back, we failed to find a profile we could connect to. - // We've come this far only so we reach the interception points - // in case they can fix things. Time to bail.... - throw CORBA::TRANSIENT (CORBA::OMGVMCID | 2, CORBA::COMPLETED_NO); - } + if (this->retry_state_ && + this->retry_state_->forward_on_exception_limit_used ()) + { + if (this->retry_state_->forward_on_exception_increment(FOE_TRANSIENT)) + { + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_INFO, + ACE_TEXT ("TAO (%P|%t) - Synch_Oneway_Invocation::") + ACE_TEXT ("remote_oneway retrying on TRANSIENT ") + ACE_TEXT ("exception\n"))); + this->retry_state_->next_profile_retry (*this->stub ()); + return TAO_INVOKE_RESTART; + } + } + else + { + // Way back, we failed to find a profile we could connect to. + // We've come this far only so we reach the interception points + // in case they can fix things. Time to bail.... + throw CORBA::TRANSIENT (CORBA::OMGVMCID | 2, CORBA::COMPLETED_NO); + } - { - ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, ace_mon, transport->output_cdr_lock (), - TAO_INVOKE_FAILURE); + } - TAO_OutputCDR &cdr = transport->out_stream (); + { + ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, ace_mon, transport->output_cdr_lock (), + TAO_INVOKE_FAILURE); - cdr.message_attributes (this->details_.request_id (), - this->resolver_.stub (), - TAO_Message_Semantics (TAO_Message_Semantics::TAO_ONEWAY_REQUEST), - max_wait_time); + TAO_OutputCDR &cdr = transport->out_stream (); - this->write_header (cdr); + cdr.message_attributes (this->details_.request_id (), + this->resolver_.stub (), + TAO_Message_Semantics (TAO_Message_Semantics::TAO_ONEWAY_REQUEST), + max_wait_time); - this->marshal_data (cdr); + this->write_header (cdr); - countdown.update (); + this->marshal_data (cdr); - if (transport->is_connected ()) - { - // We have a connected transport so we can send the message - s = this->send_message (cdr, - TAO_Message_Semantics (TAO_Message_Semantics::TAO_ONEWAY_REQUEST), - max_wait_time); + countdown.update (); - if (transport->wait_strategy ()->non_blocking () == 0 && - transport->orb_core ()->client_factory ()->use_cleanup_options ()) - { - if (!transport->wait_strategy ()->is_registered()) - { - ACE_Event_Handler * const eh = - transport->event_handler_i (); - - ACE_Reactor * const r = - transport->orb_core ()->reactor (); - - if (r->register_handler (eh, ACE_Event_Handler::READ_MASK) == -1) - { - if (TAO_debug_level > 0) - ACE_ERROR ((LM_ERROR, - "TAO (%P|%t) - Synch_Oneway_Invocation::" - "remote_oneway transport[%d] registration with" - "reactor returned an error\n", - transport->id ())); - } - else - { - // Only set this flag when registration succeeds - transport->wait_strategy ()->is_registered(true); - } - } - } + if (transport->is_connected ()) + { + // We have a connected transport so we can send the message + s = this->send_message (cdr, + TAO_Message_Semantics (TAO_Message_Semantics::TAO_ONEWAY_REQUEST), + max_wait_time); - } - else - { - if (TAO_debug_level > 4) - ACE_DEBUG ((LM_DEBUG, - "TAO (%P|%t) - Synch_Oneway_Invocation::" - "remote_oneway, queueing message\n")); + if (transport->wait_strategy ()->non_blocking () == 0 && + transport->orb_core ()->client_factory ()->use_cleanup_options ()) + { + if (!transport->wait_strategy ()->is_registered()) + { + ACE_Event_Handler * const eh = + transport->event_handler_i (); + + ACE_Reactor * const r = + transport->orb_core ()->reactor (); + + if (r->register_handler (eh, ACE_Event_Handler::READ_MASK) == -1) + { + if (TAO_debug_level > 0) + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("TAO (%P|%t) - Synch_Oneway_Invocation::") + ACE_TEXT ("remote_oneway transport[%d] registration with") + ACE_TEXT ("reactor returned an error\n"), + transport->id ())); + } + else + { + // Only set this flag when registration succeeds + transport->wait_strategy ()->is_registered (true); + } + } + } - if (transport->format_queue_message (cdr, - max_wait_time, - this->resolver_.stub()) != 0) - { - s = TAO_INVOKE_FAILURE; - } - } - } + } + else + { + if (TAO_debug_level > 4) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - Synch_Oneway_Invocation::") + ACE_TEXT ("remote_oneway, queueing message\n"))); + + if (transport->format_queue_message (cdr, + max_wait_time, + this->resolver_.stub()) != 0) + { + s = TAO_INVOKE_FAILURE; + } + } + } #if TAO_HAS_INTERCEPTORS == 1 s = this->receive_other_interception (); @@ -763,7 +863,7 @@ namespace TAO status == PortableInterceptor::TRANSPORT_RETRY) s = TAO_INVOKE_RESTART; else if (status == PortableInterceptor::SYSTEM_EXCEPTION - || status == PortableInterceptor::USER_EXCEPTION) + || status == PortableInterceptor::USER_EXCEPTION) throw; } catch (...) @@ -771,14 +871,14 @@ namespace TAO // Notify interceptors of non-CORBA exception, and propagate // that exception to the caller. - PortableInterceptor::ReplyStatus const st = - this->handle_all_exception (); + PortableInterceptor::ReplyStatus const st = + this->handle_all_exception (); - if (st == PortableInterceptor::LOCATION_FORWARD || - st == PortableInterceptor::TRANSPORT_RETRY) - s = TAO_INVOKE_RESTART; - else - throw; + if (st == PortableInterceptor::LOCATION_FORWARD || + st == PortableInterceptor::TRANSPORT_RETRY) + s = TAO_INVOKE_RESTART; + else + throw; } #endif /* TAO_HAS_INTERCEPTORS */ diff --git a/TAO/tao/Synch_Invocation.h b/TAO/tao/Synch_Invocation.h index ca01bafcbf4..bec82241379 100644 --- a/TAO/tao/Synch_Invocation.h +++ b/TAO/tao/Synch_Invocation.h @@ -36,6 +36,7 @@ class TAO_Bind_Dispatcher_Guard; namespace TAO { class Profile_Transport_Resolver; + class Invocation_Retry_State; /** * @class Synch_Twoway_Invocation @@ -82,6 +83,12 @@ namespace TAO */ Invocation_Status remote_twoway (ACE_Time_Value *max_wait_time); + /** + * Indicate that retry state should be tracked and controlled + * in the presense of exceptions. + */ + void set_retry_state (Invocation_Retry_State *retry_state); + protected: /** @@ -107,6 +114,8 @@ namespace TAO TAO_Synch_Reply_Dispatcher &rd, TAO_Bind_Dispatcher_Guard &bd); + Invocation_Retry_State *retry_state_; + private: /// Helper method that checks the reply status of the @@ -115,6 +124,7 @@ namespace TAO * This method returns an exception when there is an error. */ Invocation_Status check_reply_status (TAO_Synch_Reply_Dispatcher &rd); + }; /** diff --git a/TAO/tao/Transport.cpp b/TAO/tao/Transport.cpp index 25b70346428..b85f65966e1 100644 --- a/TAO/tao/Transport.cpp +++ b/TAO/tao/Transport.cpp @@ -143,6 +143,7 @@ TAO_Transport::TAO_Transport (CORBA::ULong tag, , recv_buffer_size_ (0) , sent_byte_count_ (0) , is_connected_ (false) + , connection_closed_on_read_ (false) , messaging_object_ (0) , char_translator_ (0) , wchar_translator_ (0) @@ -2881,6 +2882,12 @@ TAO_Transport::using_blocking_io_for_asynch_messages (void) const return false; } +bool +TAO_Transport::connection_closed_on_read (void) const +{ + return connection_closed_on_read_; +} + /* * Hook to add concrete implementations from the derived class onto * TAO's transport. diff --git a/TAO/tao/Transport.h b/TAO/tao/Transport.h index 914ede4db9b..84920bf9c7a 100644 --- a/TAO/tao/Transport.h +++ b/TAO/tao/Transport.h @@ -648,6 +648,9 @@ public: /// Is this transport really connected bool is_connected (void) const; + /// Was a connection seen as closed during a read + bool connection_closed_on_read (void) const; + /// Perform all the actions when this transport get opened bool post_open (size_t id); @@ -1183,6 +1186,12 @@ protected: /// buffer the requests in this transport until the connection is ready bool is_connected_; + /// Track if connection was seen as closed during a read so that + /// invocation can optionally be retried using a different profile. + /// Note that this could result in violate the "at most once" CORBA + /// semantics. + bool connection_closed_on_read_; + private: /// Our messaging object. diff --git a/TAO/tao/VarOut_T.h b/TAO/tao/VarOut_T.h index c1608cab33a..fd3f1f4f041 100644 --- a/TAO/tao/VarOut_T.h +++ b/TAO/tao/VarOut_T.h @@ -54,6 +54,7 @@ public: // TAO extension. T * ptr (void) const; + operator T *& (); protected: T * ptr_; @@ -113,9 +114,6 @@ public: TAO_Var_Var_T & operator= (T *); TAO_Var_Var_T & operator= (const TAO_Var_Var_T<T> &); - // Variable size types only. - operator T *& (); - operator const T & () const; operator T & (); operator T & () const; diff --git a/TAO/tao/VarOut_T.inl b/TAO/tao/VarOut_T.inl index d73084b4b16..7735ef6cefb 100644 --- a/TAO/tao/VarOut_T.inl +++ b/TAO/tao/VarOut_T.inl @@ -62,6 +62,14 @@ TAO_Var_Base_T<T>::ptr (void) const { return this->ptr_; } + +template<typename T> +ACE_INLINE +TAO_Var_Base_T<T>::operator T *& () +{ + return this->ptr_; +} + // ************************************************************* template<typename T> @@ -179,14 +187,6 @@ TAO_Var_Var_T<T>::operator= (T * p) return *this; } -// Variable-size types only. -template<typename T> -ACE_INLINE -TAO_Var_Var_T<T>::operator T *& () -{ - return this->ptr_; -} - template<typename T> ACE_INLINE TAO_Var_Var_T<T>::operator const T & () const diff --git a/TAO/tao/default_client.cpp b/TAO/tao/default_client.cpp index ac2e0c1a57c..5e3044e9b98 100644 --- a/TAO/tao/default_client.cpp +++ b/TAO/tao/default_client.cpp @@ -1,5 +1,5 @@ // -*- C++ -*- -// $Id: default_client.cpp 93686 2011-03-31 12:12:12Z johnnyw $ +// $Id$ #include "tao/default_client.h" #include "tao/Wait_On_Read.h" @@ -12,6 +12,7 @@ #include "tao/Reactive_Connect_Strategy.h" #include "tao/LF_Connect_Strategy.h" #include "tao/orbconf.h" +#include "tao/Invocation_Utils.h" #include "ace/Lock_Adapter_T.h" #include "ace/Recursive_Thread_Mutex.h" @@ -99,11 +100,13 @@ TAO_Default_Client_Strategy_Factory::parse_args (int argc, ACE_TCHAR* argv[]) ACE_TEXT("MT_NOUPCALL")) == 0) this->wait_strategy_ = TAO_WAIT_ON_LF_NO_UPCALL; else - this->report_option_value_error (ACE_TEXT("-ORBClientConnectionHandler"), name); + this->report_option_value_error ( + ACE_TEXT("-ORBClientConnectionHandler"), name); } } else if (ACE_OS::strcasecmp (argv[curarg], - ACE_TEXT("-ORBTransportMuxStrategy")) == 0) + ACE_TEXT("-ORBTransportMuxStrategy")) + == 0) { curarg++; if (curarg < argc) @@ -117,11 +120,13 @@ TAO_Default_Client_Strategy_Factory::parse_args (int argc, ACE_TCHAR* argv[]) ACE_TEXT("EXCLUSIVE")) == 0) this->transport_mux_strategy_ = TAO_EXCLUSIVE_TMS; else - this->report_option_value_error (ACE_TEXT("-ORBTransportMuxStrategy"), name); + this->report_option_value_error ( + ACE_TEXT("-ORBTransportMuxStrategy"), name); } } else if (ACE_OS::strcasecmp (argv[curarg], - ACE_TEXT("-ORBTransportMuxStrategyLock")) == 0) + ACE_TEXT("-ORBTransportMuxStrategyLock")) + == 0) { curarg++; if (curarg < argc) @@ -135,7 +140,8 @@ TAO_Default_Client_Strategy_Factory::parse_args (int argc, ACE_TCHAR* argv[]) ACE_TEXT("thread")) == 0) this->muxed_strategy_lock_type_ = TAO_THREAD_LOCK; else - this->report_option_value_error (ACE_TEXT("-ORBTransportMuxStrategyLock"), name); + this->report_option_value_error ( + ACE_TEXT("-ORBTransportMuxStrategyLock"), name); } } else if (ACE_OS::strcasecmp (argv[curarg], @@ -156,11 +162,14 @@ TAO_Default_Client_Strategy_Factory::parse_args (int argc, ACE_TCHAR* argv[]) ACE_TEXT("LF")) == 0) this->connect_strategy_ = TAO_LEADER_FOLLOWER_CONNECT; else - this->report_option_value_error (ACE_TEXT("-ORBConnectStrategy"), name); + this->report_option_value_error ( + ACE_TEXT("-ORBConnectStrategy"), + name); } } else if (ACE_OS::strcasecmp (argv[curarg], - ACE_TEXT("-ORBReplyDispatcherTableSize")) == 0) + ACE_TEXT("-ORBReplyDispatcherTableSize")) + == 0) { curarg++; if (curarg < argc) @@ -183,7 +192,118 @@ TAO_Default_Client_Strategy_Factory::parse_args (int argc, ACE_TCHAR* argv[]) ACE_OS::strcasecmp (name, ACE_TEXT("true")) == 0) this->use_cleanup_options_ = true; else - this->report_option_value_error (ACE_TEXT("-ORBConnectionHandlerCleanup"), name); + this->report_option_value_error ( + ACE_TEXT("-ORBConnectionHandlerCleanup"), name); + } + } + else if (ACE_OS::strcmp (argv[curarg], + ACE_TEXT("-ORBForwardOnCommFailureLimit")) + == 0) + { + curarg++; + if (curarg < argc) + { + ACE_TCHAR* name = argv[curarg]; + + ACE_TCHAR *err = 0; + long limit = ACE_OS::strtol (name, &err, 10); + if (err && *err != 0) + { + this->report_option_value_error ( + ACE_TEXT("-ORBForwardOnCommFailureLimit"), + name); + } + else + this->invocation_retry_params_ + .forward_on_exception_limit_[TAO::FOE_COMM_FAILURE] = + limit; + } + } + else if (ACE_OS::strcmp (argv[curarg], + ACE_TEXT("-ORBForwardOnTransientLimit")) == 0) + { + curarg++; + if (curarg < argc) + { + ACE_TCHAR* name = argv[curarg]; + + ACE_TCHAR *err = 0; + long limit = ACE_OS::strtol (name, &err, 10); + if (err && *err != 0) + { + this->report_option_value_error ( + ACE_TEXT("-ORBForwardOnTransientLimit"), + name); + } + else + this->invocation_retry_params_ + .forward_on_exception_limit_[TAO::FOE_TRANSIENT] = + limit; + } + } + else if (ACE_OS::strcmp (argv[curarg], + ACE_TEXT("-ORBForwardOnObjectNotExistLimit")) + == 0) + { + curarg++; + if (curarg < argc) + { + ACE_TCHAR* name = argv[curarg]; + + ACE_TCHAR *err = 0; + long limit = ACE_OS::strtol (name, &err, 10); + if (err && *err != 0) + { + this->report_option_value_error ( + ACE_TEXT("-ORBForwardOnObjectNotExistLimit"), + name); + } + else + this->invocation_retry_params_ + .forward_on_exception_limit_[TAO::FOE_OBJECT_NOT_EXIST] = + limit; + } + } + else if (ACE_OS::strcmp (argv[curarg], + ACE_TEXT("-ORBForwardOnInvObjrefLimit")) == 0) + { + curarg++; + if (curarg < argc) + { + ACE_TCHAR* name = argv[curarg]; + + ACE_TCHAR *err = 0; + long limit = ACE_OS::strtol (name, &err, 10); + if (err && *err != 0) + { + this->report_option_value_error ( + ACE_TEXT("-ORBForwardOnInvObjrefLimit"), name); + } + else + this->invocation_retry_params_ + .forward_on_exception_limit_[TAO::FOE_INV_OBJREF] = + limit; + } + } + else if (ACE_OS::strcmp (argv[curarg], + ACE_TEXT("-ORBForwardOnReplyClosedLimit")) + == 0) + { + curarg++; + if (curarg < argc) + { + ACE_TCHAR* name = argv[curarg]; + + ACE_TCHAR *err = 0; + long limit = ACE_OS::strtol (name, &err, 10); + if (err && *err != 0) + { + this->report_option_value_error ( + ACE_TEXT("-ORBForwardOnReplyClosedLimit"), name); + } + else + this->invocation_retry_params_ + .forward_on_reply_closed_limit_ = limit; } } else if (ACE_OS::strncmp (argv[curarg], ACE_TEXT("-ORB"), 4) == 0) @@ -208,7 +328,8 @@ TAO_Default_Client_Strategy_Factory::parse_args (int argc, ACE_TCHAR* argv[]) /// Create the correct client transport muxing strategy. TAO_Transport_Mux_Strategy * -TAO_Default_Client_Strategy_Factory::create_transport_mux_strategy (TAO_Transport *transport) +TAO_Default_Client_Strategy_Factory::create_transport_mux_strategy ( + TAO_Transport *transport) { TAO_Transport_Mux_Strategy *tms = 0; @@ -266,13 +387,14 @@ TAO_Default_Client_Strategy_Factory::reply_dispatcher_table_size (void) const } TAO_Wait_Strategy * -TAO_Default_Client_Strategy_Factory::create_wait_strategy (TAO_Transport *transport) +TAO_Default_Client_Strategy_Factory::create_wait_strategy ( + TAO_Transport *transport) { TAO_Wait_Strategy *ws = 0; /* - * Hook to customize the wait strategy object when the concrete wait strategy - * object is known a priori. + * Hook to customize the wait strategy object when the concrete + * wait strategy object is known a priori. */ //@@ WAIT_STRATEGY_SPL_COMMENT_HOOK_START switch (this->wait_strategy_) @@ -318,7 +440,8 @@ TAO_Default_Client_Strategy_Factory::connect_strategy (void) const } TAO_Connect_Strategy * -TAO_Default_Client_Strategy_Factory::create_connect_strategy (TAO_ORB_Core *orb_core) +TAO_Default_Client_Strategy_Factory::create_connect_strategy ( + TAO_ORB_Core *orb_core) { TAO_Connect_Strategy *cs = 0; @@ -374,13 +497,20 @@ TAO_Default_Client_Strategy_Factory::use_cleanup_options (void) const return this->use_cleanup_options_; } +const TAO::Invocation_Retry_Params & +TAO_Default_Client_Strategy_Factory::invocation_retry_params (void) const +{ + return this->invocation_retry_params_; +} + // **************************************************************** ACE_STATIC_SVC_DEFINE (TAO_Default_Client_Strategy_Factory, ACE_TEXT ("Client_Strategy_Factory"), ACE_SVC_OBJ_T, &ACE_SVC_NAME (TAO_Default_Client_Strategy_Factory), - ACE_Service_Type::DELETE_THIS | ACE_Service_Type::DELETE_OBJ, + ACE_Service_Type::DELETE_THIS | + ACE_Service_Type::DELETE_OBJ, 0) ACE_FACTORY_DEFINE (TAO, TAO_Default_Client_Strategy_Factory) diff --git a/TAO/tao/default_client.h b/TAO/tao/default_client.h index 3d7ea54f599..bd506384cec 100644 --- a/TAO/tao/default_client.h +++ b/TAO/tao/default_client.h @@ -22,6 +22,7 @@ #endif /* ACE_LACKS_PRAGMA_ONCE */ #include "tao/Client_Strategy_Factory.h" +#include "tao/Invocation_Retry_Params.h" TAO_BEGIN_VERSIONED_NAMESPACE_DECL @@ -61,6 +62,7 @@ public: virtual TAO_Connect_Strategy *create_connect_strategy (TAO_ORB_Core *); virtual bool use_cleanup_options (void) const; virtual Connect_Strategy connect_strategy (void) const; + virtual const TAO::Invocation_Retry_Params &invocation_retry_params (void) const; protected: void report_option_value_error (const ACE_TCHAR* option_name, @@ -104,6 +106,9 @@ private: /// Cleanupoptions for RW strategy bool use_cleanup_options_; + + /// Retry options when exceptions occur + TAO::Invocation_Retry_Params invocation_retry_params_; }; ACE_STATIC_SVC_DECLARE_EXPORT (TAO, TAO_Default_Client_Strategy_Factory) diff --git a/TAO/tao/params.cpp b/TAO/tao/params.cpp index 7adbe9e5cff..bc286c1a0e5 100644 --- a/TAO/tao/params.cpp +++ b/TAO/tao/params.cpp @@ -57,6 +57,7 @@ TAO_ORB_Parameters::TAO_ORB_Parameters (void) , stub_factory_name_ ("Default_Stub_Factory") , endpoint_selector_factory_name_ ("Default_Endpoint_Selector_Factory") , thread_lane_resources_manager_factory_name_ ("Default_Thread_Lane_Resources_Manager_Factory") + , dynamic_thread_pool_config_name_ () , poa_factory_name_ ("TAO_Object_Adapter_Factory") , poa_factory_directive_ (ACE_DYNAMIC_VERSIONED_SERVICE_DIRECTIVE("TAO_Object_Adapter_Factory", @@ -65,7 +66,7 @@ TAO_ORB_Parameters::TAO_ORB_Parameters (void) "_make_TAO_Object_Adapter_Factory", "")) , forward_invocation_on_object_not_exist_ (false) - , forward_once_exception_ (TAO::FOE_NON) + , forward_once_exception_ (0) , collocation_resolver_name_ ("Default_Collocation_Resolver") , allow_ziop_no_server_policies_ (!!TAO_ALLOW_ZIOP_NO_SERVER_POLICIES_DEFAULT) { @@ -365,6 +366,18 @@ TAO_ORB_Parameters::thread_lane_resources_manager_factory_name (void) const } void +TAO_ORB_Parameters::dynamic_thread_pool_config_name (const char *s) +{ + this->dynamic_thread_pool_config_name_ = s; +} + +const char * +TAO_ORB_Parameters::dynamic_thread_pool_config_name (void) const +{ + return this->dynamic_thread_pool_config_name_.c_str (); +} + +void TAO_ORB_Parameters::stub_factory_name (const char *s) { this->stub_factory_name_ = s; @@ -412,4 +425,28 @@ TAO_ORB_Parameters::endpoint_selector_factory_name (void) const return this->endpoint_selector_factory_name_.c_str (); } +const TAO::Invocation_Retry_Params & +TAO_ORB_Parameters::invocation_retry_params (void) const +{ + return this->invocation_retry_params_; +} + +TAO::Invocation_Retry_Params & +TAO_ORB_Parameters::invocation_retry_params (void) +{ + return this->invocation_retry_params_; +} + +void +TAO_ORB_Parameters::forward_on_exception_limit (const int ef, const int limit) +{ + this->invocation_retry_params_.forward_on_exception_limit_[ef] = limit; +} + +void +TAO_ORB_Parameters::forward_on_exception_delay (const ACE_Time_Value &delay) +{ + this->invocation_retry_params_.init_retry_delay_ = delay; +} + TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/tao/params.h b/TAO/tao/params.h index 90c5c80c4e4..b9c91ebaaa1 100644 --- a/TAO/tao/params.h +++ b/TAO/tao/params.h @@ -14,9 +14,11 @@ #define TAO_PARAMS_H #include /**/ "ace/pre.h" +#include "tao/Invocation_Retry_Params.h" #include "ace/Unbounded_Queue.h" #include "ace/Array_Map.h" #include "ace/Synch.h" +#include "ace/Time_Value.h" #if !defined (ACE_LACKS_PRAGMA_ONCE) # pragma once @@ -42,6 +44,8 @@ typedef ACE_Unbounded_Queue_Const_Iterator<ACE_CString> TAO_EndpointSetIterator; // ------------------------------------------------------------------- + + /** * @class TAO_ORB_Parameters * @@ -237,6 +241,9 @@ public: void thread_lane_resources_manager_factory_name (const char *s); const char *thread_lane_resources_manager_factory_name (void) const; + void dynamic_thread_pool_config_name (const char *s); + const char *dynamic_thread_pool_config_name (void) const; + void stub_factory_name (const char *s); const char *stub_factory_name (void) const; @@ -255,7 +262,13 @@ public: void forward_invocation_on_object_not_exist (bool opt); bool forward_invocation_on_object_not_exist (void) const; - void forward_once_exception (const int); + void forward_on_exception_limit (const int ef, const int limit); + void forward_on_exception_delay (const ACE_Time_Value &delay); + + TAO::Invocation_Retry_Params &invocation_retry_params (void); + const TAO::Invocation_Retry_Params &invocation_retry_params (void) const; + + void forward_once_exception (const int ef); int forward_once_exception () const; void allow_ziop_no_server_policies (bool opt); @@ -458,6 +471,13 @@ private: ACE_CString thread_lane_resources_manager_factory_name_; /** + * Name of the non-RT dynamic thread pool configuration set to load. + * This is only used if the Dynamic_TP library is linked. Default + * is an empty string. + */ + ACE_CString dynamic_thread_pool_config_name_; + + /** * Name of the service object used to create the RootPOA. The * default value is "TAO_POA". If TAO_RTCORBA is loaded, this * will be changed to TAO_RT_POA so that a POA equipped with @@ -478,13 +498,15 @@ private: */ bool forward_invocation_on_object_not_exist_; + TAO::Invocation_Retry_Params invocation_retry_params_; /** * The exceptions upon which the requests will be forwarded once. + * This is retained for backward compatibility of behavior. */ int forward_once_exception_; - /** +/** * Name of the collocation resolver that needs to be instantiated. * The default value is "Default_Collocation_Resolver". If * TAO_RTCORBA is linked, the set_collocation_resolver will be diff --git a/TAO/tao/tao.mpc b/TAO/tao/tao.mpc index b26544fbf41..e2aff7dbe5c 100644 --- a/TAO/tao/tao.mpc +++ b/TAO/tao/tao.mpc @@ -174,6 +174,8 @@ project(TAO) : acelib, install, tao_output, taodefaults, pidl, extra_core, taoid Invocation_Adapter.cpp Invocation_Base.cpp Invocation_Endpoint_Selectors.cpp + Invocation_Retry_State.cpp + Invocation_Retry_Params.cpp IOPC.cpp IOR_Parser.cpp IORInterceptor_Adapter.cpp @@ -274,6 +276,10 @@ project(TAO) : acelib, install, tao_output, taodefaults, pidl, extra_core, taoid ShortSeqC.cpp String_Alloc.cpp StringSeqC.cpp + Storable_Base.cpp + Storable_FlatFileStream.cpp + Storable_Factory.cpp + Storable_File_Guard.cpp Stub.cpp Stub_Factory.cpp Synch_Invocation.cpp |