PG_GenericFactory.cpp

Go to the documentation of this file.
00001 #include "orbsvcs/PortableGroup/PG_GenericFactory.h"
00002 #include "orbsvcs/PortableGroup/PG_MemberInfo.h"
00003 #include "orbsvcs/PortableGroup/PG_ObjectGroupManager.h"
00004 #include "orbsvcs/PortableGroup/PG_PropertyManager.h"
00005 #include "orbsvcs/PortableGroup/PG_Property_Utils.h"
00006 #include "orbsvcs/PortableGroup/PG_conf.h"
00007 
00008 #include "ace/OS_NS_stdio.h"
00009 
00010 #include "tao/ORB_Constants.h"
00011 
00012 ACE_RCSID (PortableGroup,
00013            PG_GenericFactory,
00014            "PG_GenericFactory.cpp,v 1.26 2006/03/14 06:14:34 jtc Exp")
00015 
00016 
00017 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00018 
00019 TAO_PG_GenericFactory::TAO_PG_GenericFactory (
00020   TAO_PG_ObjectGroupManager & object_group_manager,
00021   TAO_PG_PropertyManager & property_manager)
00022   : poa_ (),
00023     object_group_manager_ (object_group_manager),
00024     property_manager_ (property_manager),
00025     factory_map_ (TAO_PG_MAX_OBJECT_GROUPS),
00026     next_fcid_ (0),
00027     lock_ ()
00028 {
00029   this->object_group_manager_.generic_factory (this);
00030 }
00031 
00032 TAO_PG_GenericFactory::~TAO_PG_GenericFactory (void)
00033 {
00034   ACE_DECLARE_NEW_CORBA_ENV;
00035 
00036   TAO_PG_Factory_Map::iterator end = this->factory_map_.end ();
00037   for (TAO_PG_Factory_Map::iterator i = this->factory_map_.begin ();
00038        i != end;
00039        ++i)
00040     {
00041       TAO_PG_Factory_Set & factory_set = (*i).int_id_;
00042 
00043       ACE_TRY
00044         {
00045           this->delete_object_i (factory_set,
00046                                  1 /* Ignore exceptions */
00047                                  ACE_ENV_ARG_PARAMETER);
00048           ACE_TRY_CHECK;
00049         }
00050       ACE_CATCHANY
00051         {
00052           // Ignore all exceptions.
00053         }
00054       ACE_ENDTRY;
00055     }
00056 
00057   (void) this->factory_map_.close ();
00058 }
00059 
00060 CORBA::Object_ptr
00061 TAO_PG_GenericFactory::create_object (
00062     const char * type_id,
00063     const PortableGroup::Criteria & the_criteria,
00064     PortableGroup::GenericFactory::FactoryCreationId_out factory_creation_id
00065     ACE_ENV_ARG_DECL)
00066   ACE_THROW_SPEC ((CORBA::SystemException,
00067                    PortableGroup::NoFactory,
00068                    PortableGroup::ObjectNotCreated,
00069                    PortableGroup::InvalidCriteria,
00070                    PortableGroup::InvalidProperty,
00071                    PortableGroup::CannotMeetCriteria))
00072 {
00073   PortableGroup::Properties_var properties =
00074     this->property_manager_.get_type_properties (type_id
00075                                                  ACE_ENV_ARG_PARAMETER);
00076   ACE_CHECK_RETURN (CORBA::Object::_nil ());
00077 
00078   PortableGroup::MembershipStyleValue membership_style =
00079     TAO_PG_MEMBERSHIP_STYLE;
00080   PortableGroup::FactoriesValue factory_infos(0);
00081 
00082   PortableGroup::InitialNumberMembersValue initial_number_members =
00083     TAO_PG_INITIAL_NUMBER_MEMBERS;
00084   PortableGroup::MinimumNumberMembersValue minimum_number_members =
00085     TAO_PG_MINIMUM_NUMBER_MEMBERS;
00086 
00087   // Make sure the criteria for the object group being created are
00088   // valid.
00089   this->process_criteria (type_id,
00090                           the_criteria,
00091                           membership_style,
00092                           factory_infos,
00093                           initial_number_members,
00094                           minimum_number_members
00095                           ACE_ENV_ARG_PARAMETER);
00096   ACE_CHECK_RETURN (CORBA::Object::_nil ());
00097 
00098   CORBA::ULong fcid = 0;
00099 
00100   {
00101     ACE_GUARD_RETURN (TAO_SYNCH_MUTEX,
00102                       guard,
00103                       this->lock_,
00104                       CORBA::Object::_nil ());
00105 
00106     // Start out with an initial value.
00107     fcid = this->next_fcid_;
00108 
00109     // Loop until a free FactoryCreationId is found, being careful to
00110     // search through the range of FactoryCreationIds only once.
00111     while (this->factory_map_.find (this->next_fcid_) == 0)
00112       {
00113         this->next_fcid_++;
00114 
00115         // If this is true, then no FactoryCreationIds are available.
00116         // This is highly unlikely since TAO implements a
00117         // FactoryCreationId as a 32 bit unsigned integer, meaning
00118         // that over 4 billion object groups are being managed by this
00119         // generic factory!
00120         if (this->next_fcid_ == fcid)
00121           ACE_THROW_RETURN (PortableGroup::ObjectNotCreated (),
00122                             CORBA::Object::_nil ());
00123       }
00124 
00125     // Just in case this->next_fcid_ was modified in the above search,
00126     // reassign the value.
00127     fcid = this->next_fcid_;
00128   }
00129 
00130   // The ObjectId for the newly created object group is comprised
00131   // solely of the FactoryCreationId.
00132   PortableServer::ObjectId_var oid;
00133   this->get_ObjectId (fcid, oid.out ());
00134 
00135   PortableGroup::ObjectGroup_var object_group =
00136     this->object_group_manager_.create_object_group (fcid,
00137                                                      oid.in (),
00138                                                      type_id,
00139                                                      the_criteria
00140                                                      ACE_ENV_ARG_PARAMETER);
00141   ACE_CHECK_RETURN (CORBA::Object::_nil ());
00142 
00143   TAO_PG_Factory_Set factory_set;
00144 
00145   const CORBA::ULong factory_infos_count = factory_infos.length ();
00146 
00147   ACE_TRY
00148     {
00149       if (factory_infos_count > 0
00150           && membership_style == PortableGroup::MEMB_INF_CTRL)
00151         {
00152           this->populate_object_group (object_group.in (),
00153                                        type_id,
00154                                        factory_infos,
00155                                        initial_number_members,
00156                                        factory_set
00157                                        ACE_ENV_ARG_PARAMETER);
00158           ACE_TRY_CHECK;
00159 
00160           if (this->factory_map_.bind (fcid, factory_set) != 0)
00161             ACE_TRY_THROW (PortableGroup::ObjectNotCreated ());
00162 
00163         }
00164 
00165       // Allocate a new FactoryCreationId for use as an "out" parameter.
00166       PortableGroup::GenericFactory::FactoryCreationId * tmp = 0;
00167       ACE_NEW_THROW_EX (tmp,
00168                         PortableGroup::GenericFactory::FactoryCreationId,
00169                         CORBA::NO_MEMORY (
00170                           CORBA::SystemException::_tao_minor_code (
00171                             TAO::VMCID,
00172                             ENOMEM),
00173                           CORBA::COMPLETED_NO));
00174       ACE_CHECK_RETURN (CORBA::Object::_nil ());
00175 
00176       factory_creation_id = tmp;
00177 
00178       *tmp <<= fcid;
00179     }
00180   ACE_CATCHANY
00181     {
00182       this->delete_object_i (factory_set,
00183                              1 /* Ignore exceptions */
00184                              ACE_ENV_ARG_PARAMETER);
00185       ACE_TRY_CHECK;
00186 
00187       this->object_group_manager_.destroy_object_group (oid.in ()
00188                                                         ACE_ENV_ARG_PARAMETER);
00189       ACE_TRY_CHECK;
00190 
00191       ACE_RE_THROW;
00192     }
00193   ACE_ENDTRY;
00194   ACE_CHECK_RETURN (CORBA::Object::_nil ());
00195 
00196   {
00197     ACE_GUARD_RETURN (TAO_SYNCH_MUTEX,
00198                       guard,
00199                       this->lock_,
00200                       CORBA::Object::_nil ());
00201 
00202     // Object group was successfully created.  Increment the next
00203     // FactoryCreationId in preparation for the next object group.
00204     this->next_fcid_++;
00205   }
00206 
00207   return object_group._retn ();
00208 }
00209 
00210 void
00211 TAO_PG_GenericFactory::delete_object (
00212     const PortableGroup::GenericFactory::FactoryCreationId &
00213       factory_creation_id
00214     ACE_ENV_ARG_DECL)
00215   ACE_THROW_SPEC ((CORBA::SystemException,
00216                    PortableGroup::ObjectNotFound))
00217 {
00218   CORBA::ULong fcid = 0;
00219 
00220   if (factory_creation_id >>= fcid) // Extract the actual FactoryCreationId.
00221     {
00222       // Successfully extracted the FactoryCreationId.  Now find the
00223       // TAO_PG_Factory_Set corresponding to it.
00224 
00225       ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->lock_);
00226 
00227       // If no entry exists in the factory map, infrastructure
00228       // controlled membership was not used.
00229       TAO_PG_Factory_Map::ENTRY *entry = 0;
00230       if (this->factory_map_.find (fcid, entry) == 0)
00231         {
00232           TAO_PG_Factory_Set & factory_set = entry->int_id_;
00233 
00234           this->delete_object_i (factory_set,
00235                                  0  /* Do not ignore exceptions */
00236                                  ACE_ENV_ARG_PARAMETER);
00237           ACE_CHECK;
00238 
00239           if (this->factory_map_.unbind (fcid) != 0)
00240             ACE_THROW (CORBA::INTERNAL ());
00241         }
00242     }
00243   else
00244     ACE_THROW (PortableGroup::ObjectNotFound ());  // @@
00245                                                    //    CORBA::BAD_PARAM
00246                                                    //    instead?
00247 
00248   // The ObjectId for the newly created object group is comprised
00249   // solely of the FactoryCreationId.
00250   PortableServer::ObjectId_var oid;
00251   this->get_ObjectId (fcid, oid.out ());
00252 
00253   // Destroy the object group entry.
00254   this->object_group_manager_.destroy_object_group (
00255     oid.in ()
00256     ACE_ENV_ARG_PARAMETER);
00257   ACE_CHECK;
00258 }
00259 
00260 void
00261 TAO_PG_GenericFactory::delete_object_i (TAO_PG_Factory_Set & factory_set,
00262                                         CORBA::Boolean ignore_exceptions
00263                                         ACE_ENV_ARG_DECL)
00264 {
00265   const size_t len = factory_set.size ();
00266 
00267   size_t ilen = len;
00268   for (size_t i = 0; i != len; ++i)
00269     {
00270       // Destroy the object group member in reverse order in case the
00271       // array list is only partially destroyed and another call to
00272       // GenericFactory::delete_object() occurs afterwards.
00273       --ilen;
00274 
00275       TAO_PG_Factory_Node & factory_node = factory_set[ilen];
00276 
00277       PortableGroup::GenericFactory_ptr factory =
00278         factory_node.factory_info.the_factory.in ();
00279       const PortableGroup::GenericFactory::FactoryCreationId & member_fcid =
00280         factory_node.factory_creation_id.in ();
00281 
00282       ACE_TRY
00283         {
00284           factory->delete_object (member_fcid
00285                                   ACE_ENV_ARG_PARAMETER);
00286           ACE_TRY_CHECK;
00287         }
00288       ACE_CATCHANY
00289         {
00290           // Exceptions are generally only ignored when this
00291           // GenericFactory (not the one being invoked above) is
00292           // destroyed.  The idea is to allow the GenericFactory to be
00293           // destroyed regardless of whether or not all object group
00294           // members have been destroyed, and minimize the number of
00295           // object group members that have not been destroyed.
00296           if (!ignore_exceptions)
00297             ACE_RE_THROW;
00298         }
00299       ACE_ENDTRY;
00300       ACE_CHECK;
00301 
00302       // Since GenericFactory::delete_object() can throw an exception,
00303       // decrease the size of the factory array incrementally since
00304       // some object group members may not have been destroyed yet.
00305       // Note that this size reduction is fast since no memory is
00306       // actually deallocated.
00307       factory_set.size (ilen);
00308     }
00309 }
00310 
00311 void
00312 TAO_PG_GenericFactory::delete_member (
00313   CORBA::ULong group_id,
00314   const PortableGroup::Location & location
00315   ACE_ENV_ARG_DECL)
00316 {
00317   ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->lock_);
00318 
00319   // If no entry exists in the factory map, infrastructure
00320   // controlled membership was not used.
00321   TAO_PG_Factory_Map::ENTRY *entry = 0;
00322   if (this->factory_map_.find (group_id, entry) == 0)
00323     {
00324       TAO_PG_Factory_Set & factory_set = entry->int_id_;
00325 
00326       const size_t len = factory_set.size ();
00327 
00328       // Iterate through the factory_set until a location match
00329       // occurs.  If a location match occurs, the member was created
00330       // by the infrastructure, i.e. this GenericFactory
00331       // implementation.  If no location matches, the member was
00332       // created by the application, and no operation will be
00333       // performed.
00334       //
00335       // @todo This is linear search.  Change to use a container with
00336       //       better search times.
00337       for (size_t i = 0; i < len; ++i)
00338         {
00339           TAO_PG_Factory_Node & node = factory_set[i];
00340           PortableGroup::FactoryInfo & info = node.factory_info;
00341 
00342           if (info.the_location == location)
00343             {
00344               info.the_factory->delete_object (node.factory_creation_id.in ()
00345                                                ACE_ENV_ARG_PARAMETER);
00346               ACE_CHECK;
00347 
00348               // The member has been successfully deleted.  Reduce the
00349               // size of the factory_set accordingly.
00350               if (len > 1)
00351                 {
00352                   // Move the last element to the location of the
00353                   // current one and reduce the size of the set by
00354                   // one.
00355                   const size_t new_len = len - 1;
00356                   node = factory_set[new_len]; // Memberwise copy
00357                   factory_set.size (new_len);
00358                 }
00359               else
00360                 {
00361                   // A copy isn't necessary if the last member was
00362                   // deleted.
00363                   factory_set.size (0);
00364                 }
00365 
00366               return;
00367             }
00368         }
00369     }
00370 }
00371 
00372 void
00373 TAO_PG_GenericFactory::poa (PortableServer::POA_ptr p)
00374 {
00375   ACE_ASSERT (CORBA::is_nil (this->poa_.in ())
00376               && !CORBA::is_nil (p));
00377 
00378   this->poa_ = PortableServer::POA::_duplicate (p);
00379 }
00380 
00381 void
00382 TAO_PG_GenericFactory::populate_object_group (
00383   PortableGroup::ObjectGroup_ptr object_group,
00384   const char * type_id,
00385   const PortableGroup::FactoryInfos & factory_infos,
00386   PortableGroup::InitialNumberMembersValue initial_number_members,
00387   TAO_PG_Factory_Set & factory_set
00388   ACE_ENV_ARG_DECL)
00389 {
00390   CORBA::ULong factory_infos_count = factory_infos.length ();
00391   factory_set.size (factory_infos_count);
00392 
00393   for (CORBA::ULong j = 0; j < factory_infos_count; ++j)
00394     {
00395       TAO_PG_Factory_Node & factory_node = factory_set[j];
00396 
00397       const PortableGroup::FactoryInfo &factory_info = factory_infos[j];
00398 
00399       if (j < static_cast<CORBA::ULong> (initial_number_members))
00400         {
00401           PortableGroup::GenericFactory_ptr factory =
00402             factory_info.the_factory.in ();
00403 
00404           if (CORBA::is_nil (factory))
00405             {
00406               // @@ instead InvalidProperty?
00407               ACE_THROW (PortableGroup::NoFactory (factory_info.the_location,
00408                                                    type_id));
00409             }
00410 
00411           // Do not allow the PortableGroup::MemberAlreadyPresent
00412           // exception to be propagated to this scope.
00413           const CORBA::Boolean propagate_member_already_present = 0;
00414 
00415           factory_node.factory_creation_id =
00416             this->create_member (object_group,
00417                                  factory_info,
00418                                  type_id,
00419                                  propagate_member_already_present
00420                                  ACE_ENV_ARG_PARAMETER);
00421           ACE_CHECK;
00422         }
00423 
00424       factory_node.factory_info = factory_info;  // Memberwise copy
00425     }
00426 }
00427 
00428 void
00429 TAO_PG_GenericFactory::get_ObjectId (
00430   CORBA::ULong fcid,
00431   PortableServer::ObjectId_out oid)
00432 {
00433   // Since the POA used by the LoadManager uses the NON_RETAIN
00434   // policy, explicitly choose an ObjectId that is unique to a given
00435   // type.
00436 
00437   // Make the ObjectId be the next value of the number of types that
00438   // have been registered with the LoadManager.  For example, if two
00439   // types of objects have been registered with the LoadManager, then
00440   // the ObjectId for the object currently being registered will be
00441   // "3" since the object will be the third type of object registered
00442   // with the LoadManager.  Previously used values will not be reused
00443   // to ensure that a ServantLocator does not inadvertently return a
00444   // reference to an object that had a previously used ObjectId.
00445   // Specifcally, the numerical value used for the ObjectId increases
00446   // monotonically.
00447 
00448   // 4294967295UL -- Largest 32 bit unsigned integer
00449   // 123456789012 -- 10 digits
00450   //                + 2 for "UL"  (unnecessary, but let's be safe)
00451   //                + 1 for null terminator
00452   //                + 1 for good luck. :-)
00453   const size_t MAX_OID_LEN = 14;
00454 
00455   char oid_str[MAX_OID_LEN] = { 0 };
00456   ACE_OS::sprintf (oid_str,
00457                    "%ul",
00458                    fcid);
00459 
00460   oid = PortableServer::string_to_ObjectId (oid_str);
00461 }
00462 
00463 void
00464 TAO_PG_GenericFactory::process_criteria (
00465   const char * type_id,
00466   const PortableGroup::Criteria & criteria,
00467   PortableGroup::MembershipStyleValue & membership_style,
00468   PortableGroup::FactoriesValue & factory_infos,
00469   PortableGroup::InitialNumberMembersValue & initial_number_members,
00470   PortableGroup::MinimumNumberMembersValue & minimum_number_members
00471   ACE_ENV_ARG_DECL)
00472 {
00473   // Get type-specific properties.
00474   PortableGroup::Properties_var props =
00475     this->property_manager_.get_type_properties (type_id
00476                                                  ACE_ENV_ARG_PARAMETER);
00477   ACE_CHECK;
00478 
00479   // Merge the given criteria with the type-specific criteria.
00480   TAO_PG::override_properties (criteria, props.inout ());
00481 
00482   PortableGroup::Criteria unmet_criteria;
00483   unmet_criteria.length (4);  // The four criteria understood by this
00484                               // method.
00485 
00486   // Unmet criteria count.
00487   CORBA::ULong uc = 0;
00488 
00489   PortableGroup::Name name (1);
00490   name.length (1);
00491 
00492   PortableGroup::Value value;
00493   PortableGroup::Value value1;
00494   PortableGroup::Value value2;
00495   PortableGroup::Value value3;
00496 
00497   // MembershipStyle
00498   name[0].id = CORBA::string_dup ("org.omg.PortableGroup.MembershipStyle");
00499   if (TAO_PG::get_property_value (name, props.in (), value)
00500       && (!(value >>= membership_style)
00501           || (membership_style != PortableGroup::MEMB_APP_CTRL
00502               && membership_style != PortableGroup::MEMB_INF_CTRL)))
00503     {
00504       // This only occurs if extraction of the actual value from the
00505       // Any fails.
00506       ACE_THROW (PortableGroup::InvalidProperty (name, value));
00507     }
00508 
00509   // Factories
00510   const PortableGroup::FactoryInfos * factory_infos_tmp = 0;
00511   name[0].id = CORBA::string_dup ("org.omg.PortableGroup.Factories");
00512   if (TAO_PG::get_property_value (name, props.in (), value1)
00513       && !(value1 >>= factory_infos_tmp))
00514     {
00515       // This only occurs if extraction of the actual value from the
00516       // Any fails.
00517       ACE_THROW (PortableGroup::InvalidProperty (name, value1));
00518     }
00519 
00520   const CORBA::ULong factory_infos_count =
00521     (factory_infos_tmp == 0 ? 0 : factory_infos_tmp->length ());
00522 
00523   // InitialNumberMembers
00524   name[0].id =
00525     CORBA::string_dup ("org.omg.PortableGroup.InitialNumberMembers");
00526   if (TAO_PG::get_property_value (name, props.in (), value2)
00527       && !(value2 >>= initial_number_members))
00528     {
00529       // This only occurs if extraction of the actual value from the
00530       // Any fails.
00531       ACE_THROW (PortableGroup::InvalidProperty (name, value2));
00532     }
00533 
00534   if (membership_style == PortableGroup::MEMB_INF_CTRL)
00535     {
00536       // If the number of factories is less than the initial number of
00537       // members or the desired number of initial members cannot
00538       // possibly be created.
00539 
00540       if (factory_infos_count < static_cast<CORBA::ULong> (initial_number_members))
00541         {
00542           unmet_criteria[uc].nam = name;
00543           unmet_criteria[uc++].val = value2;
00544         }
00545     }
00546 
00547   // MinimumNumberMembers
00548   name[0].id =
00549     CORBA::string_dup ("org.omg.PortableGroup.MinimumNumberMembers");
00550   if (TAO_PG::get_property_value (name, props.in (), value3)
00551       && !(value3 >>= minimum_number_members))
00552     {
00553       // This only occurs if extraction of the actual value from the
00554       // Any fails.
00555       ACE_THROW (PortableGroup::InvalidProperty (name, value3));
00556     }
00557 
00558   // If the minimum number of members is less than the initial number
00559   // of members, the MinimumNumberMembers property is cannot be
00560   // initially met.
00561   //
00562   // @note This code is not part of the above "MEMB_INF_CTRL" criteria
00563   //       check since the "name" and "value" variables have been
00564   //       changed.
00565   if (membership_style == PortableGroup::MEMB_INF_CTRL)
00566     {
00567       if (minimum_number_members < initial_number_members
00568           || static_cast<CORBA::ULong> (minimum_number_members) > factory_infos_count)
00569         {
00570           unmet_criteria[uc].nam = name;
00571           unmet_criteria[uc++].val = value3;
00572         }
00573       else if (factory_infos_tmp != 0)
00574       {
00575         factory_infos.length (factory_infos_count);
00576         factory_infos = *factory_infos_tmp;
00577       }
00578     }
00579 
00580   if (uc > 0)
00581     {
00582       // Reduce the length of the unmet criteria sequence in an effort
00583       // to optimize the copying that will occur when the below
00584       // exception is thrown.  Reducing the length is fast since no
00585       // deallocations should occur.
00586       unmet_criteria.length (uc);
00587 
00588       ACE_THROW (PortableGroup::CannotMeetCriteria (unmet_criteria));
00589     }
00590 }
00591 
00592 void
00593 TAO_PG_GenericFactory::check_minimum_number_members (
00594   PortableGroup::ObjectGroup_ptr object_group,
00595   CORBA::ULong group_id,
00596   const char * type_id
00597   ACE_ENV_ARG_DECL)
00598 {
00599   // Check if we've dropped below the MinimumNumberMembers threshold.
00600   // If so, attempt to create enough new members to fill the gap.
00601 
00602   // If no entry exists in the factory map, infrastructure (this
00603   // GenericFactory implementation) controlled membership was not
00604   // used.
00605   TAO_PG_Factory_Map::ENTRY *entry = 0;
00606   if (this->factory_map_.find (group_id, entry) != 0)
00607     return;
00608 
00609   TAO_PG_Factory_Set & factory_set = entry->int_id_;
00610 
00611   PortableGroup::Properties_var props =
00612     this->property_manager_.get_properties (object_group
00613                                             ACE_ENV_ARG_PARAMETER);
00614   ACE_CHECK;
00615 
00616   PortableGroup::Name name (1);
00617   name.length (1);
00618 
00619   PortableGroup::Value value;
00620 
00621   // MinimumNumberMembers
00622   name[0].id =
00623     CORBA::string_dup ("org.omg.PortableGroup.MinimumNumberMembers");
00624 
00625   PortableGroup::MinimumNumberMembersValue minimum_number_members;
00626 
00627   if (TAO_PG::get_property_value (name, props.in (), value))
00628     {
00629       if (!(value >>= minimum_number_members))
00630         {
00631           // This only occurs if extraction of the actual value from
00632           // the Any fails.  It shouldn't fail at this point.
00633           ACE_THROW (CORBA::INTERNAL ());
00634         }
00635 
00636       const CORBA::ULong count =
00637         this->object_group_manager_.member_count (object_group
00638                                                   ACE_ENV_ARG_PARAMETER);
00639       ACE_CHECK;
00640 
00641       if (count >= static_cast<CORBA::ULong> (minimum_number_members))
00642         return;
00643 
00644       const CORBA::ULong gap =
00645         static_cast<CORBA::ULong> (minimum_number_members) - count;
00646 
00647       CORBA::ULong creation_count = 0;
00648 
00649       const size_t len = factory_set.size ();
00650 
00651       static const PortableGroup::GenericFactory::FactoryCreationId *
00652         nil_fcid = 0;
00653 
00654       for (size_t i = 0; i < len; ++i)
00655         {
00656           TAO_PG_Factory_Node & node = factory_set[i];
00657 
00658           PortableGroup::GenericFactory::FactoryCreationId * const tmp_fcid =
00659             node.factory_creation_id;
00660 
00661           // Check if the application supplied GenericFactory was
00662           // already invoked.
00663           if (tmp_fcid != nil_fcid)
00664             continue;
00665 
00666           ACE_TRY
00667             {
00668               const CORBA::Boolean propagate_member_already_present = 1;
00669 
00670               node.factory_creation_id =
00671                 this->create_member (object_group,
00672                                      node.factory_info,
00673                                      type_id,
00674                                      propagate_member_already_present
00675                                      ACE_ENV_ARG_PARAMETER);
00676               ACE_TRY_CHECK;
00677 
00678               ++creation_count;
00679 
00680               // Check if the MinimumNumberMembers threshold gap has
00681               // been filled.
00682               if (gap == creation_count)
00683                 return;
00684             }
00685           ACE_CATCH (PortableGroup::MemberAlreadyPresent, ex)
00686             {
00687               // Ignore this exception and continue.
00688             }
00689           ACE_ENDTRY;
00690           ACE_CHECK;
00691         }
00692 
00693       // @todo If we get this far, and the MinimumNumberMembers
00694       //       threshold gap hasn't been filled, what do we do?  Throw
00695       //       a CORBA::TRANSIENT?
00696     }
00697 }
00698 
00699 PortableGroup::GenericFactory::FactoryCreationId *
00700 TAO_PG_GenericFactory::create_member (
00701     PortableGroup::ObjectGroup_ptr object_group,
00702     const PortableGroup::FactoryInfo & factory_info,
00703     const char * type_id,
00704     const CORBA::Boolean propagate_member_already_present
00705     ACE_ENV_ARG_DECL)
00706   ACE_THROW_SPEC ((CORBA::SystemException,
00707                    PortableGroup::NoFactory,
00708                    PortableGroup::ObjectNotCreated,
00709                    PortableGroup::InvalidCriteria,
00710                    PortableGroup::InvalidProperty,
00711                    PortableGroup::CannotMeetCriteria,
00712                    PortableGroup::MemberAlreadyPresent))
00713 {
00714   PortableGroup::GenericFactory::FactoryCreationId_var fcid;
00715 
00716   CORBA::Object_var member =
00717     factory_info.the_factory->create_object (type_id,
00718                                              factory_info.the_criteria,
00719                                              fcid.out ()
00720                                              ACE_ENV_ARG_PARAMETER);
00721   ACE_CHECK_RETURN (0);
00722 
00723   ACE_TRY
00724     {
00725       // @@ Should an "_is_a()" be performed here?  While it
00726       //    appears to be the right thing to do, it can be
00727       //    expensive.
00728       //
00729       // Make sure an Object of the correct type was created.
00730       // It is possible that an object of the wrong type was
00731       // created if the type_id parameter does not match the
00732       // type of object the GenericFactory creates.
00733       CORBA::Boolean right_type_id =
00734         member->_is_a (type_id
00735                        ACE_ENV_ARG_PARAMETER);
00736       ACE_TRY_CHECK;
00737 
00738       // @todo Strategize this -- e.g. strict type checking.
00739       if (!right_type_id)
00740         {
00741           // An Object of incorrect type was created.  Delete
00742           // it, and throw a NoFactory exception.
00743           factory_info.the_factory->delete_object (fcid.in ()
00744                                                    ACE_ENV_ARG_PARAMETER);
00745           ACE_TRY_CHECK;
00746 
00747           ACE_TRY_THROW (PortableGroup::NoFactory (factory_info.the_location,
00748                                                    type_id));
00749         }
00750 
00751       this->object_group_manager_._tao_add_member (
00752         object_group,
00753         factory_info.the_location,
00754         member.in (),
00755         type_id,
00756         propagate_member_already_present
00757         ACE_ENV_ARG_PARAMETER);
00758       ACE_TRY_CHECK;
00759     }
00760   ACE_CATCHANY
00761     {
00762       // If the member reference is not nil, then the factory
00763       // was successfully invoked.  Since an exception was
00764       // thrown, clean up the up created member.
00765       if (!CORBA::is_nil (member.in ()))
00766         {
00767           factory_info.the_factory->delete_object (fcid.in ()
00768                                                    ACE_ENV_ARG_PARAMETER);
00769           ACE_TRY_CHECK;
00770         }
00771 
00772       ACE_RE_THROW;
00773     }
00774   ACE_ENDTRY;
00775   ACE_CHECK_RETURN (0);
00776 
00777   return fcid._retn ();
00778 }
00779 
00780 TAO_END_VERSIONED_NAMESPACE_DECL

Generated on Thu Nov 9 14:03:33 2006 for TAO_PortableGroup by doxygen 1.3.6