ServantRetentionStrategyRetain.cpp

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

Generated on Sun Jan 27 13:23:44 2008 for TAO_PortableServer by doxygen 1.3.6