ServantRetentionStrategyRetain.cpp

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

Generated on Thu Nov 9 12:40:45 2006 for TAO_PortableServer by doxygen 1.3.6