ServantRetentionStrategyRetain.cpp

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 //=============================================================================
00004 /**
00005  *  @file    ServantRetentionStrategyRetain.cpp
00006  *
00007  *  $Id: ServantRetentionStrategyRetain.cpp 81665 2008-05-09 13:37:40Z parsons $
00008  *
00009  */
00010 //=============================================================================
00011 
00012 #include "tao/ORB_Core.h"
00013 #include "tao/debug.h"
00014 #include "tao/PortableServer/ServantRetentionStrategyRetain.h"
00015 #include "tao/PortableServer/Non_Servant_Upcall.h"
00016 #include "tao/PortableServer/Servant_Upcall.h"
00017 #include "tao/PortableServer/POA_Current_Impl.h"
00018 #include "tao/PortableServer/Root_POA.h"
00019 #include "tao/PortableServer/Active_Object_Map.h"
00020 #include "tao/PortableServer/Active_Object_Map_Entry.h"
00021 
00022 #if defined (TAO_HAS_MONITOR_POINTS) && (TAO_HAS_MONITOR_POINTS == 1)
00023 #include "ace/Monitor_Size.h"
00024 #endif /* TAO_HAS_MONITOR_POINTS */
00025 
00026 ACE_RCSID (PortableServer,
00027            ServantRetentionStrategyRetain,
00028            "$Id: ServantRetentionStrategyRetain.cpp 81665 2008-05-09 13:37:40Z parsons $")
00029 
00030 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00031 
00032 namespace TAO
00033 {
00034   namespace Portable_Server
00035   {
00036     ServantRetentionStrategyRetain::ServantRetentionStrategyRetain (void) :
00037       ServantRetentionStrategyNonRetain (),
00038       active_object_map_ (),
00039       waiting_servant_deactivation_ (0)
00040     {
00041     }
00042 
00043     void
00044     ServantRetentionStrategyRetain::strategy_init (TAO_Root_POA *poa)
00045     {
00046       poa_ = poa;
00047 
00048       // Create the active object map to be used
00049       TAO_Active_Object_Map *active_object_map = 0;
00050       ACE_NEW_THROW_EX (active_object_map,
00051                         TAO_Active_Object_Map (!poa->system_id (),
00052                                                !poa->allow_multiple_activations (),
00053                                                poa->is_persistent (),
00054                                                poa->orb_core().server_factory ()->active_object_map_creation_parameters ()
00055                                               ), CORBA::NO_MEMORY ());
00056 
00057       ACE_auto_ptr_reset (this->active_object_map_, active_object_map);
00058 
00059 #if defined (TAO_HAS_MONITOR_POINTS) && (TAO_HAS_MONITOR_POINTS == 1)
00060       ACE_CString name_str ("Active_Object_Map_");
00061       name_str += poa->the_name ();
00062       active_object_map->monitor_->name (name_str.c_str ());
00063       active_object_map->monitor_->add_to_registry ();
00064 #endif /* TAO_HAS_MONITOR_POINTS */
00065     }
00066 
00067     void
00068     ServantRetentionStrategyRetain::strategy_cleanup (void)
00069     {
00070     }
00071 
00072     void
00073     ServantRetentionStrategyRetain::deactivate_object (
00074       const PortableServer::ObjectId &id)
00075     {
00076       TAO_Active_Object_Map_Entry *active_object_map_entry = 0;
00077       int const result = this->active_object_map_->
00078         find_entry_using_user_id (id, active_object_map_entry);
00079 
00080       // If there is no active object associated with the specified Object
00081       // Id, the operation raises an ObjectNotActive exception.
00082       if (result != 0)
00083         {
00084           throw PortableServer::POA::ObjectNotActive ();
00085         }
00086 
00087       this->deactivate_map_entry (active_object_map_entry);
00088     }
00089 
00090     void
00091     ServantRetentionStrategyRetain::deactivate_map_entry (
00092       TAO_Active_Object_Map_Entry *active_object_map_entry)
00093     {
00094       // Decrement the reference count.
00095       CORBA::UShort const new_count = --active_object_map_entry->reference_count_;
00096 
00097       // Inform the custom servant dispatching (CSD) strategy that the
00098       // servant is deactivated. This would be called just once when the
00099       // servant is deactivated the first time.
00100       if (active_object_map_entry->deactivated_ == 0)
00101         {
00102           this->poa_->servant_deactivated_hook (
00103             active_object_map_entry->servant_,
00104             active_object_map_entry->user_id_);
00105         }
00106 
00107       if (new_count == 0)
00108         {
00109           this->poa_->cleanup_servant (active_object_map_entry->servant_,
00110                                        active_object_map_entry->user_id_);
00111         }
00112       else
00113         {
00114           // It should be noted that there may be a period of time between
00115           // an object's deactivation and the etherealization (during
00116           // which outstanding requests are being processed) in which
00117           // arriving requests on that object should not be passed to its
00118           // servant. During this period, requests targeted for such an
00119           // object act as if the POA were in holding state until
00120           // etherealize completes. If etherealize is called as a
00121           // consequence of a deactivate call with a etherealize_objects
00122           // parameter of TRUE, incoming requests are rejected.
00123 
00124           // Else mark entry as closed...
00125           active_object_map_entry->deactivated_ = 1;
00126         }
00127     }
00128 
00129     int
00130     ServantRetentionStrategyRetain::unbind_using_user_id (
00131       const PortableServer::ObjectId &user_id)
00132     {
00133       return this->active_object_map_->unbind_using_user_id (user_id);
00134     }
00135 
00136     PortableServer::Servant
00137     ServantRetentionStrategyRetain::find_servant (
00138       const PortableServer::ObjectId &system_id)
00139     {
00140       // Find user id from system id.
00141       PortableServer::ObjectId_var user_id;
00142       if (active_object_map_->
00143           find_user_id_using_system_id (system_id, user_id.out()) != 0)
00144         {
00145           throw ::CORBA::OBJ_ADAPTER ();
00146         }
00147 
00148       // This operation returns the active servant associated with the
00149       // specified system Object Id value.  If the Object Id value is
00150       // not active in the POA, an ObjectNotActive exception is
00151       // raised.
00152       TAO_Active_Object_Map_Entry *entry = 0;
00153       PortableServer::Servant servant = 0;
00154 
00155       int const result =
00156         active_object_map_->
00157           find_servant_using_system_id_and_user_id (system_id,
00158                                                     user_id.in(),
00159                                                     servant,
00160                                                     entry);
00161 
00162       if (result == -1)
00163         {
00164           throw PortableServer::POA::ObjectNotActive ();
00165         }
00166 
00167       return servant;
00168     }
00169 
00170     PortableServer::ObjectId *
00171     ServantRetentionStrategyRetain::system_id_to_object_id (
00172       const PortableServer::ObjectId &system_id)
00173     {
00174       // The object denoted by the reference does not have to be
00175       // active for this operation to succeed.
00176       PortableServer::ObjectId_var user_id;
00177       if (this->active_object_map_->
00178           find_user_id_using_system_id (system_id,
00179                                         user_id.out ()) != 0)
00180         {
00181           throw ::CORBA::OBJ_ADAPTER ();
00182         }
00183 
00184       return user_id._retn ();
00185     }
00186 
00187     PortableServer::Servant
00188     ServantRetentionStrategyRetain::user_id_to_servant (
00189       const PortableServer::ObjectId &id)
00190     {
00191       // If the POA has the RETAIN policy and the specified ObjectId is in
00192       // the Active Object Map, this operation returns the servant
00193       // associated with that object in the Active Object Map.
00194       PortableServer::Servant servant = 0;
00195 
00196       if (this->active_object_map_->find_servant_using_user_id (id, servant) == -1)
00197         {
00198           throw PortableServer::POA::ObjectNotActive ();
00199         }
00200 
00201       return servant;
00202     }
00203 
00204     CORBA::Object_ptr
00205     ServantRetentionStrategyRetain::id_to_reference (
00206       const PortableServer::ObjectId &id,
00207       bool indirect)
00208     {
00209       // If an object with the specified Object Id value is currently
00210       // active, a reference encapsulating the information used to
00211       // activate the object is returned.
00212       PortableServer::ObjectId_var system_id;
00213       PortableServer::Servant servant;
00214       CORBA::Short priority;
00215 
00216       if (this->active_object_map_->
00217           find_servant_and_system_id_using_user_id (id,
00218                                                     servant,
00219                                                     system_id.out (),
00220                                                     priority) == 0)
00221         {
00222           // Remember params for potentially invoking <key_to_object> later.
00223           this->poa_->key_to_object_params_.set (system_id,
00224                                                  servant->_interface_repository_id (),
00225                                                  servant,
00226                                                  1,
00227                                                  priority,
00228                                                  indirect);
00229 
00230           return this->poa_->invoke_key_to_object_helper_i (servant->_interface_repository_id (),
00231                                                             id);
00232         }
00233       else
00234         {
00235           // If the Object Id value is not active in the POA, an
00236           // ObjectNotActive exception is raised.
00237           throw PortableServer::POA::ObjectNotActive ();
00238         }
00239     }
00240 
00241     TAO_SERVANT_LOCATION
00242     ServantRetentionStrategyRetain::servant_present (
00243       const PortableServer::ObjectId &system_id,
00244       PortableServer::Servant &servant)
00245     {
00246       // Find user id from system id.
00247       PortableServer::ObjectId_var user_id;
00248       if (this->active_object_map_->
00249           find_user_id_using_system_id (system_id, user_id.out()) != 0)
00250         {
00251           throw ::CORBA::OBJ_ADAPTER ();
00252         }
00253 
00254       TAO_Active_Object_Map_Entry *entry = 0;
00255       int const result = this->active_object_map_->
00256         find_servant_using_system_id_and_user_id (system_id,
00257                                                   user_id.in(),
00258                                                   servant,
00259                                                   entry);
00260       if (result == 0)
00261         {
00262           // Success
00263           return TAO_SERVANT_FOUND;
00264         }
00265       else
00266         {
00267           return TAO_SERVANT_NOT_FOUND;
00268         }
00269     }
00270 
00271     PortableServer::Servant
00272     ServantRetentionStrategyRetain::find_servant (
00273       const PortableServer::ObjectId &system_id,
00274       TAO::Portable_Server::Servant_Upcall &servant_upcall,
00275       TAO::Portable_Server::POA_Current_Impl &poa_current_impl)
00276     {
00277       PortableServer::ObjectId user_id;
00278       // If we have the RETAIN policy, convert/transform from system id to
00279       // user id.
00280       if (this->active_object_map_->
00281           find_user_id_using_system_id (system_id,
00282                                         user_id) != 0)
00283         {
00284           throw ::CORBA::OBJ_ADAPTER ();
00285         }
00286 
00287       poa_current_impl.object_id(user_id);
00288       servant_upcall.user_id (&poa_current_impl.object_id());
00289 
00290       // If the POA has the RETAIN policy, the POA looks in the Active
00291       // Object Map to find if there is a servant associated with the
00292       // Object Id value from the request. If such a servant exists, the
00293       // POA invokes the appropriate method on the servant.
00294       PortableServer::Servant servant = 0;
00295       TAO_Active_Object_Map_Entry *active_object_map_entry = 0;
00296       int const result = this->active_object_map_->
00297         find_servant_using_system_id_and_user_id (system_id,
00298                                                   user_id,
00299                                                   servant,
00300                                                   active_object_map_entry);
00301 
00302 
00303       if (result == 0)
00304         {
00305           servant_upcall.active_object_map_entry (active_object_map_entry);
00306 
00307           // Increment the reference count.
00308           servant_upcall.increment_servant_refcount ();
00309         }
00310 
00311       return servant;
00312     }
00313 
00314     int
00315     ServantRetentionStrategyRetain::find_servant_priority (
00316         const PortableServer::ObjectId &system_id,
00317         CORBA::Short &priority)
00318     {
00319       PortableServer::ObjectId user_id;
00320       // If we have the RETAIN policy, convert/transform from system id to
00321       // user id.
00322       if (this->active_object_map_->
00323           find_user_id_using_system_id (system_id,
00324                                         user_id) != 0)
00325         {
00326           throw ::CORBA::OBJ_ADAPTER ();
00327         }
00328 
00329       // If the POA has the RETAIN policy, the POA looks in the Active
00330       // Object Map to find if there is a servant associated with the
00331       // Object Id value from the request. If such a servant exists, the
00332       // POA invokes the appropriate method on the servant.
00333       PortableServer::Servant servant = 0;
00334       TAO_Active_Object_Map_Entry *active_object_map_entry = 0;
00335       int const result = this->active_object_map_->
00336         find_servant_using_system_id_and_user_id (system_id,
00337                                                   user_id,
00338                                                   servant,
00339                                                   active_object_map_entry);
00340 
00341       if (result == 0)
00342         {
00343           priority = active_object_map_entry->priority_;
00344           return 0;
00345         }
00346 
00347       return -1;
00348     }
00349 
00350     int
00351     ServantRetentionStrategyRetain::is_servant_in_map (
00352       PortableServer::Servant servant,
00353       bool &wait_occurred_restart_call)
00354     {
00355       bool deactivated = false;
00356       int servant_in_map =
00357         this->active_object_map_->is_servant_in_map (servant, deactivated);
00358 
00359       if (!servant_in_map)
00360         {
00361           return 0;
00362         }
00363       else
00364         {
00365           if (deactivated)
00366             {
00367               if (TAO_debug_level > 0)
00368                 ACE_DEBUG ((LM_DEBUG,
00369                             ACE_TEXT ("(%t) TAO_Root_POA::is_servant_in_map: waiting for servant to deactivate\n")));
00370 
00371               // We are going to wait on this condition variable; the POA
00372               // state may change by the time we get the lock again.
00373               // Therefore, indicate to the caller that all conditions
00374               // need to be checked again.
00375               wait_occurred_restart_call = true;
00376 
00377               ++this->waiting_servant_deactivation_;
00378 
00379               if (this->poa_->object_adapter ().enable_locking ())
00380                 this->poa_->servant_deactivation_condition ().wait ();
00381 
00382               --this->waiting_servant_deactivation_;
00383 
00384               return 0;
00385             }
00386           else
00387             {
00388               return 1;
00389             }
00390         }
00391     }
00392 
00393     int
00394     ServantRetentionStrategyRetain::is_user_id_in_map (
00395       const PortableServer::ObjectId &id,
00396       CORBA::Short priority,
00397       bool &priorities_match,
00398       bool &wait_occurred_restart_call)
00399     {
00400       bool deactivated = false;
00401       bool user_id_in_map =
00402         this->active_object_map_->is_user_id_in_map (id,
00403                                                       priority,
00404                                                       priorities_match,
00405                                                       deactivated);
00406 
00407       if (!user_id_in_map)
00408         {
00409           return 0;
00410         }
00411       else
00412         {
00413           if (deactivated)
00414             {
00415               if (TAO_debug_level > 0)
00416                 ACE_DEBUG ((LM_DEBUG,
00417                             ACE_TEXT ("(%t) TAO_Root_POA::is_user_id_in_map: waiting for servant to deactivate\n")));
00418 
00419               // We are going to wait on this condition variable; the POA
00420               // state may change by the time we get the lock again.
00421               // Therefore, indicate to the caller that all conditions
00422               // need to be checked again.
00423               wait_occurred_restart_call = 1;
00424 
00425               ++this->waiting_servant_deactivation_;
00426 
00427               if (this->poa_->object_adapter ().enable_locking ())
00428                 this->poa_->servant_deactivation_condition ().wait ();
00429 
00430               --this->waiting_servant_deactivation_;
00431 
00432               return 0;
00433             }
00434           else
00435             {
00436               return 1;
00437             }
00438         }
00439     }
00440 
00441     CORBA::ULong
00442     ServantRetentionStrategyRetain::waiting_servant_deactivation (void) const
00443     {
00444       return waiting_servant_deactivation_;
00445     }
00446 
00447     void
00448     ServantRetentionStrategyRetain::deactivate_all_objects (void)
00449     {
00450       // If the etherealize_objects parameter is TRUE, the POA has the
00451       // RETAIN policy, and a servant manager is registered with the POA,
00452       // the etherealize operation on the servant manager will be called
00453       // for each active object in the Active Object Map. The apparent
00454       // destruction of the POA occurs before any calls to etherealize are
00455       // made.  Thus, for example, an etherealize method that attempts to
00456       // invoke operations on the POA will receive the OBJECT_NOT_EXIST
00457       // exception.
00458 
00459       // We must copy the map entries into a separate place since we
00460       // cannot remove entries while iterating through the map.
00461       ACE_Array_Base<TAO_Active_Object_Map_Entry *> map_entries
00462         (this->active_object_map_->current_size ());
00463 
00464       size_t counter = 0;
00465       TAO_Active_Object_Map::user_id_map::iterator end
00466         = this->active_object_map_->user_id_map_->end ();
00467 
00468       for (TAO_Active_Object_Map::user_id_map::iterator iter
00469               = this->active_object_map_->user_id_map_->begin ();
00470             iter != end;
00471             ++iter)
00472         {
00473           TAO_Active_Object_Map::user_id_map::value_type map_pair = *iter;
00474           TAO_Active_Object_Map_Entry *active_object_map_entry = map_pair.second ();
00475 
00476           if (!active_object_map_entry->deactivated_)
00477             {
00478               map_entries[counter] = active_object_map_entry;
00479               ++counter;
00480             }
00481         }
00482 
00483       for (size_t i = 0;
00484             i < counter;
00485             ++i)
00486         {
00487           this->deactivate_map_entry (map_entries[i]);
00488         }
00489     }
00490 
00491     PortableServer::ObjectId *
00492     ServantRetentionStrategyRetain::servant_to_user_id (
00493       PortableServer::Servant servant)
00494     {
00495       // This operation requires the RETAIN and either the UNIQUE_ID or
00496       // IMPLICIT_ACTIVATION policies; if not present, the WrongPolicy
00497       // exception is raised.
00498       if (!((!this->poa_->allow_multiple_activations ()
00499                 || this->poa_->allow_implicit_activation ())))
00500         {
00501           throw PortableServer::POA::WrongPolicy ();
00502         }
00503 
00504       /**
00505        * If the POA has both the RETAIN and the UNIQUE_ID policy and the
00506        * specified servant is active, the Object Id associated with that
00507        * servant is returned.
00508        *
00509        * If the POA has both the RETAIN and the IMPLICIT_ACTIVATION policy and
00510        * either the POA has the MULTIPLE_ID policy or the specified servant is
00511        * not active, the servant is activated using a POA-generated Object Id
00512        * and the Interface Id associated with the servant, and that Object Id
00513        * is returned.
00514        *
00515        */
00516 
00517       // If the POA has the UNIQUE_ID policy and the specified servant is
00518       // active, the Object Id associated with that servant is returned.
00519       PortableServer::ObjectId_var user_id;
00520       if (!this->poa_->allow_multiple_activations () &&
00521           this->active_object_map_->
00522           find_user_id_using_servant (servant, user_id.out ()) != -1)
00523         {
00524           return user_id._retn ();
00525         }
00526 
00527       // If the POA has the IMPLICIT_ACTIVATION policy and either the POA
00528       // has the MULTIPLE_ID policy or the specified servant is not
00529       // active, the servant is activated using a POA-generated Object Id
00530       // and the Interface Id associated with the servant, and that Object
00531       // Id is returned.
00532       if (this->poa_->allow_implicit_activation ())
00533         {
00534           // If we reach here, then we either have the MULTIPLE_ID policy
00535           // or we have the UNIQUE_ID policy and we are not in the active
00536           // object map.
00537           PortableServer::ObjectId_var user_id;
00538           if (this->active_object_map_->
00539               bind_using_system_id_returning_user_id (servant,
00540                                                       this->poa_->server_priority (),
00541                                                       user_id.out ()) != 0)
00542             {
00543               throw ::CORBA::OBJ_ADAPTER ();
00544             }
00545 
00546           //
00547           // Everything is finally ok
00548           //
00549 
00550           // Inform the custom servant dispatching (CSD) strategy that the
00551           // sevant is activated.
00552           this->poa_->servant_activated_hook (servant, user_id.in ());
00553 
00554           // ATTENTION: Trick locking here, see class header for details
00555           Non_Servant_Upcall non_servant_upcall (*this->poa_);
00556           ACE_UNUSED_ARG (non_servant_upcall);
00557 
00558           // If this operation causes the object to be activated, _add_ref
00559           // is invoked at least once on the Servant argument before
00560           // returning. Otherwise, the POA does not increment or decrement
00561           // the reference count of the Servant passed to this function.
00562           servant->_add_ref ();
00563 
00564           return user_id._retn ();
00565         }
00566 
00567       /*
00568        * Otherwise, the ServantNotActive exception is raised.
00569        */
00570       throw PortableServer::POA::ServantNotActive ();
00571     }
00572 
00573     PortableServer::ObjectId *
00574     ServantRetentionStrategyRetain::servant_to_system_id_i (
00575       PortableServer::Servant servant,
00576       CORBA::Short &priority)
00577     {
00578       // This operation requires the RETAIN and either the UNIQUE_ID or
00579       // IMPLICIT_ACTIVATION policies; if not present, the WrongPolicy
00580       // exception is raised.
00581       if (!((!this->poa_->allow_multiple_activations ()
00582                 || this->poa_->allow_implicit_activation ())))
00583         {
00584           throw PortableServer::POA::WrongPolicy ();
00585         }
00586 
00587       // This operation has three possible behaviors.
00588 
00589       // If the POA has the UNIQUE_ID policy and the specified servant is
00590       // active, the Object Id associated with that servant is returned.
00591       PortableServer::ObjectId_var system_id;
00592       if (!this->poa_->allow_multiple_activations () &&
00593           this->active_object_map_->
00594           find_system_id_using_servant (servant,
00595                                         system_id.out (),
00596                                         priority) != -1)
00597         {
00598           return system_id._retn ();
00599         }
00600 
00601 #if defined (CORBA_E_COMPACT) || defined (CORBA_E_MICRO)
00602       // CORBA e does not allow implicit activation.
00603       // At this point we can throw the WrongPolicy exception.
00604       throw PortableServer::POA::WrongPolicy ();
00605 #endif /* CORBA_E_COMPACT || CORBA_E_MICRO */
00606 
00607       // If the POA has the IMPLICIT_ACTIVATION policy and either the POA
00608       // has the MULTIPLE_ID policy or the specified servant is not
00609       // active, the servant is activated using a POA-generated Object Id
00610       // and the Interface Id associated with the servant, and that Object
00611       // Id is returned.
00612       if (this->poa_->allow_implicit_activation ())
00613         {
00614           // If we reach here, then we either have the MULTIPLE_ID policy
00615           // or we have the UNIQUE_ID policy and we are not in the active
00616           // object map.
00617           PortableServer::ObjectId_var system_id;
00618           if (this->active_object_map_->
00619               bind_using_system_id_returning_system_id (servant,
00620                                                         priority,
00621                                                         system_id.out ()) != 0)
00622             {
00623               throw ::CORBA::OBJ_ADAPTER ();
00624             }
00625 
00626           //
00627           // Everything is finally ok
00628           //
00629 
00630           // Inform the custom servant dispatching (CSD) strategy that the
00631           // sevant is activated.
00632           this->poa_->servant_activated_hook (servant, system_id.in ());
00633 
00634           // ATTENTION: Trick locking here, see class header for details
00635           Non_Servant_Upcall non_servant_upcall (*this->poa_);
00636           ACE_UNUSED_ARG (non_servant_upcall);
00637 
00638           // If this operation causes the object to be activated, _add_ref
00639           // is invoked at least once on the Servant argument before
00640           // returning. Otherwise, the POA does not increment or decrement
00641           // the reference count of the Servant passed to this function.
00642           servant->_add_ref ();
00643 
00644           return system_id._retn ();
00645         }
00646 
00647       // Otherwise, the ServantNotActive exception is raised.
00648       throw PortableServer::POA::ServantNotActive ();
00649     }
00650 
00651     CORBA::Object_ptr
00652     ServantRetentionStrategyRetain::servant_to_reference (
00653       PortableServer::Servant servant)
00654     {
00655       // Note: The allocation of an Object Id value and installation in
00656       // the Active Object Map caused by implicit activation may actually
00657       // be deferred until an attempt is made to externalize the
00658       // reference. The real requirement here is that a reference is
00659       // produced that will behave appropriately (that is, yield a
00660       // consistent Object Id value when asked politely).
00661       CORBA::Short priority = this->poa_->server_priority ();
00662 
00663       PortableServer::ObjectId_var system_id =
00664         this->servant_to_system_id_i (servant, priority);
00665 
00666       PortableServer::ObjectId user_id;
00667 
00668       // This operation requires the RETAIN, therefore don't worry about
00669       // the NON_RETAIN case.
00670       if (this->active_object_map_->
00671           find_user_id_using_system_id (system_id.in (), user_id) != 0)
00672         {
00673           throw ::CORBA::OBJ_ADAPTER ();
00674         }
00675 
00676       // Remember params for potentially invoking <key_to_object> later.
00677       this->poa_->key_to_object_params_.set (
00678         system_id,
00679         servant->_interface_repository_id (),
00680         servant,
00681         1,
00682         priority,
00683         true);
00684 
00685       // Ask the ORT to create the object.
00686       // @@NOTE:There is a possible deadlock lurking here. We held the
00687       // lock, and we are possibly trying to make a call into the
00688       // application code. Think what would happen if the app calls us
00689       // back. We need to get to this at some point.
00690       return this->poa_->invoke_key_to_object_helper_i (
00691               servant->_interface_repository_id (), user_id);
00692     }
00693 
00694     PortableServer::ObjectId *
00695     ServantRetentionStrategyRetain::activate_object (
00696       PortableServer::Servant servant,
00697       CORBA::Short priority,
00698       bool &wait_occurred_restart_call)
00699     {
00700       if (!this->poa_->has_system_id ())
00701         {
00702           throw PortableServer::POA::WrongPolicy ();
00703         }
00704 
00705       bool may_activate =
00706         this->poa_->is_servant_activation_allowed (servant, wait_occurred_restart_call);
00707 
00708       if (!may_activate)
00709         {
00710           if (wait_occurred_restart_call)
00711             {
00712               return 0;
00713             }
00714           else
00715             {
00716               throw PortableServer::POA::ServantAlreadyActive ();
00717             }
00718         }
00719 
00720       // Otherwise, the activate_object operation generates an Object Id
00721       // and enters the Object Id and the specified servant in the Active
00722       // Object Map. The Object Id is returned.
00723       PortableServer::ObjectId_var user_id;
00724       if (this->active_object_map_->
00725           bind_using_system_id_returning_user_id (servant,
00726                                                   priority,
00727                                                   user_id.out ()) != 0)
00728         {
00729           throw ::CORBA::OBJ_ADAPTER ();
00730         }
00731 
00732       //
00733       // Everything is finally ok
00734       //
00735 
00736       // Inform the custom servant dispatching (CSD) strategy that the
00737       // sevant is activated.
00738       this->poa_->servant_activated_hook (servant, user_id.in ());
00739 
00740       // ATTENTION: Trick locking here, see class header for details
00741       Non_Servant_Upcall non_servant_upcall (*this->poa_);
00742       ACE_UNUSED_ARG (non_servant_upcall);
00743 
00744       // The implementation of activate_object will invoke _add_ref at
00745       // least once on the Servant argument before returning. When the POA
00746       // no longer needs the Servant, it will invoke _remove_ref on it the
00747       // same number of times.
00748       servant->_add_ref ();
00749 
00750       return user_id._retn ();
00751     }
00752 
00753 #if !defined (CORBA_E_MICRO)
00754     void
00755     ServantRetentionStrategyRetain::activate_object_with_id (
00756       const PortableServer::ObjectId &id,
00757       PortableServer::Servant servant,
00758       CORBA::Short priority,
00759       bool &wait_occurred_restart_call)
00760     {
00761       // If the POA has the SYSTEM_ID policy and it detects that the
00762       // Object Id value was not generated by the system or for this POA,
00763       // the activate_object_with_id operation may raise the BAD_PARAM
00764       // system exception.  An ORB is not required to detect all such
00765       // invalid Object Id values, but a portable application must not
00766       // invoke activate_object_with_id on a POA that has the SYSTEM_ID
00767       // policy with an Object Id value that was not previously generated
00768       // by the system for that POA, or, if the POA also has the
00769       // PERSISTENT policy, for a previous instantiation of the same POA.
00770       if (this->poa_->has_system_id () &&
00771           !this->poa_->is_poa_generated_id (id))
00772         {
00773           throw ::CORBA::BAD_PARAM ();
00774         }
00775 
00776       // If the CORBA object denoted by the Object Id value is already
00777       // active in this POA (there is a servant bound to it in the Active
00778       // Object Map), the ObjectAlreadyActive exception is raised.
00779       bool priorities_match = true;
00780       bool result =
00781         this->is_user_id_in_map (id,
00782                                  priority,
00783                                  priorities_match,
00784                                  wait_occurred_restart_call);
00785 
00786     // @johnny the implementation is not complete, this does the spec also say
00787     // If the POA has the UNIQUE_ID policy and the servant is already
00788     // in the Active Object Map, the ServantAlreadyActive exception is raised.
00789       if (result)
00790         {
00791           throw PortableServer::POA::ObjectAlreadyActive ();
00792         }
00793       else if (wait_occurred_restart_call)
00794         {
00795           // We ended up waiting on a condition variable, the POA state
00796           // may have changed while we are waiting.  Therefore, we need to
00797           // restart this call.
00798           return;
00799         }
00800 
00801       // If the activate_object_with_id_and_priority operation is invoked
00802       // with a different priority to an earlier invocation of one of the
00803       // create reference with priority operations, for the same object,
00804       // then the ORB shall raise a BAD_INV_ORDER system exception (with a
00805       // Standard Minor Exception Code of 1). If the priority value is the
00806       // same then the ORB shall return SUCCESS.
00807       if (!priorities_match)
00808         {
00809           throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID | 1,
00810                                         CORBA::COMPLETED_NO);
00811         }
00812 
00813       bool const may_activate =
00814         this->poa_->is_servant_activation_allowed (servant, wait_occurred_restart_call);
00815 
00816       if (!may_activate)
00817         {
00818           if (wait_occurred_restart_call)
00819             {
00820               return;
00821             }
00822           else
00823             {
00824               throw PortableServer::POA::ServantAlreadyActive ();
00825             }
00826         }
00827 
00828       // Otherwise, the activate_object_with_id operation enters an
00829       // association between the specified Object Id and the specified
00830       // servant in the Active Object Map.
00831       if (this->active_object_map_->bind_using_user_id (servant,
00832                                                         id,
00833                                                         priority) != 0)
00834         {
00835           throw ::CORBA::OBJ_ADAPTER ();
00836         }
00837 
00838       //
00839       // Everything is finally ok
00840       //
00841 
00842       // Inform the custom servant dispatching (CSD) strategy that the
00843       // sevant is activated.
00844       this->poa_->servant_activated_hook (servant, id);
00845 
00846       // ATTENTION: Trick locking here, see class header for details
00847       Non_Servant_Upcall non_servant_upcall (*this->poa_);
00848       ACE_UNUSED_ARG (non_servant_upcall);
00849 
00850       // The implementation of activate_object_with_id will invoke
00851       // _add_ref at least once on the Servant argument before
00852       // returning. When the POA no longer needs the Servant, it will
00853       // invoke _remove_ref on it the same number of times.
00854       servant->_add_ref ();
00855     }
00856 #endif
00857 
00858     CORBA::Object_ptr
00859     ServantRetentionStrategyRetain::create_reference (
00860       const char *intf,
00861       CORBA::Short priority)
00862     {
00863       // This operation creates an object reference that encapsulates a
00864       // POA-generated Object Id value and the specified interface
00865       // repository id. This operation does not cause an activation to
00866       // take place. The resulting reference may be passed to clients, so
00867       // that subsequent requests on those references will cause the
00868       // appropriate servant manager to be invoked, if one is
00869       // available. The generated Object Id value may be obtained by
00870       // invoking POA::reference_to_id with the created reference.
00871 
00872       PortableServer::ObjectId_var system_id;
00873       PortableServer::ObjectId user_id;
00874 
00875       if (this->active_object_map_->
00876           bind_using_system_id_returning_system_id (0,
00877                                                     priority,
00878                                                     system_id.out ()) != 0)
00879         {
00880           throw ::CORBA::OBJ_ADAPTER ();
00881         }
00882 
00883       // Find user id from system id.
00884       if (this->active_object_map_->
00885           find_user_id_using_system_id (system_id.in (),
00886                                         user_id) != 0)
00887         {
00888           throw ::CORBA::OBJ_ADAPTER ();
00889         }
00890 
00891       // Remember params for potentially invoking <key_to_object> later.
00892       this->poa_->key_to_object_params_.set (system_id,
00893                                        intf,
00894                                        0,
00895                                        1,
00896                                        priority,
00897                                        true);
00898 
00899       return this->poa_->invoke_key_to_object_helper_i (intf,
00900                                                         user_id);
00901     }
00902 
00903 #if !defined (CORBA_E_MICRO)
00904     CORBA::Object_ptr
00905     ServantRetentionStrategyRetain::create_reference_with_id (
00906       const PortableServer::ObjectId &oid,
00907       const char *intf,
00908       CORBA::Short priority)
00909     {
00910       // This operation creates an object reference that encapsulates the
00911       // specified Object Id and interface repository Id values. This
00912       // operation does not cause an activation to take place.  The
00913       // resulting reference may be passed to clients, so that subsequent
00914       // requests on those references will cause the object to be
00915       // activated if necessary, or the default servant used, depending on
00916       // the applicable policies.
00917 
00918       PortableServer::Servant servant = 0;
00919       PortableServer::ObjectId_var system_id;
00920 
00921       // @@ We need something that can find the system id using
00922       // appropriate strategy, at the same time, return the servant if
00923       // one is available.  Before we have that function,
00924       // <create_reference_with_id_i> basically generates broken
00925       // collocated object when DIRECT collocation strategy is used.
00926 
00927       if (this->active_object_map_->
00928           find_system_id_using_user_id (oid,
00929                                         priority,
00930                                         system_id.out ()) != 0)
00931         {
00932           throw ::CORBA::OBJ_ADAPTER ();
00933         }
00934 
00935       // Remember params for potentially invoking <key_to_object> later.
00936       this->poa_->key_to_object_params_.set (system_id,
00937                                        intf,
00938                                        servant,
00939                                        1,
00940                                        priority,
00941                                        true);
00942 
00943       return this->poa_->invoke_key_to_object_helper_i (intf, oid);
00944     }
00945 #endif
00946 
00947     int
00948     ServantRetentionStrategyRetain::rebind_using_user_id_and_system_id (
00949       PortableServer::Servant servant,
00950       const PortableServer::ObjectId &user_id,
00951       const PortableServer::ObjectId &system_id,
00952       TAO::Portable_Server::Servant_Upcall &servant_upcall)
00953     {
00954       TAO_Active_Object_Map_Entry *entry = 0;
00955       int result = this->active_object_map_->
00956         rebind_using_user_id_and_system_id (servant,
00957                                             user_id,
00958                                             system_id,
00959                                             entry);
00960       servant_upcall.active_object_map_entry(entry);
00961 
00962       return result;
00963     }
00964 
00965     CORBA::Boolean
00966     ServantRetentionStrategyRetain::servant_has_remaining_activations (
00967       PortableServer::Servant servant)
00968     {
00969       return this->active_object_map_->remaining_activations (servant);
00970     }
00971 
00972 
00973     ::PortableServer::ServantRetentionPolicyValue
00974     ServantRetentionStrategyRetain::type(void) const
00975     {
00976       return ::PortableServer::RETAIN;
00977     }
00978 
00979   }
00980 }
00981 
00982 TAO_END_VERSIONED_NAMESPACE_DECL

Generated on Tue Feb 2 17:40:54 2010 for TAO_PortableServer by  doxygen 1.4.7