Updated logging to include the class/method so that it is more obvious where these...
[ACE_TAO.git] / TAO / tao / PortableServer / ServantRetentionStrategyRetain.cpp
blobefcd7935078ffe061a64bfb50cd902d6c6428d1b
1 // -*- C++ -*-
3 //=============================================================================
4 /**
5 * @file ServantRetentionStrategyRetain.cpp
6 */
7 //=============================================================================
9 #include "tao/ORB_Core.h"
10 #include "tao/debug.h"
11 #include "tao/PortableServer/ServantRetentionStrategyRetain.h"
12 #include "tao/PortableServer/Non_Servant_Upcall.h"
13 #include "tao/PortableServer/Servant_Upcall.h"
14 #include "tao/PortableServer/POA_Current_Impl.h"
15 #include "tao/PortableServer/Root_POA.h"
16 #include "tao/PortableServer/Active_Object_Map.h"
17 #include "tao/PortableServer/Active_Object_Map_Entry.h"
19 #if defined (TAO_HAS_MONITOR_POINTS) && (TAO_HAS_MONITOR_POINTS == 1)
20 #include "ace/Monitor_Size.h"
21 #endif /* TAO_HAS_MONITOR_POINTS */
23 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
25 namespace TAO
27 namespace Portable_Server
29 ServantRetentionStrategyRetain::ServantRetentionStrategyRetain () :
30 ServantRetentionStrategyNonRetain (),
31 active_object_map_ (),
32 waiting_servant_deactivation_ (0)
36 void
37 ServantRetentionStrategyRetain::strategy_init (TAO_Root_POA *poa)
39 poa_ = poa;
41 // Create the active object map to be used
42 TAO_Active_Object_Map *active_object_map = 0;
43 ACE_NEW_THROW_EX (active_object_map,
44 TAO_Active_Object_Map (!poa->system_id (),
45 !poa->allow_multiple_activations (),
46 poa->is_persistent (),
47 poa->orb_core().server_factory ()->active_object_map_creation_parameters ()
48 ), CORBA::NO_MEMORY ());
50 this->active_object_map_.reset (active_object_map);
52 #if defined (TAO_HAS_MONITOR_POINTS) && (TAO_HAS_MONITOR_POINTS == 1)
53 ACE_CString name_str ("Active_Object_Map_");
54 name_str += poa->orb_core ().orbid ();
55 name_str += '_';
56 name_str += poa->the_name ();
58 active_object_map->monitor_->name (name_str.c_str ());
59 active_object_map->monitor_->add_to_registry ();
60 #endif /* TAO_HAS_MONITOR_POINTS */
63 void
64 ServantRetentionStrategyRetain::strategy_cleanup ()
68 void
69 ServantRetentionStrategyRetain::deactivate_object (
70 const PortableServer::ObjectId &id)
72 TAO_Active_Object_Map_Entry *active_object_map_entry = 0;
73 int const result = this->active_object_map_->
74 find_entry_using_user_id (id, active_object_map_entry);
76 // If there is no active object associated with the specified Object
77 // Id, the operation raises an ObjectNotActive exception.
78 if (result != 0)
80 throw PortableServer::POA::ObjectNotActive ();
83 this->deactivate_map_entry (active_object_map_entry);
86 void
87 ServantRetentionStrategyRetain::deactivate_map_entry (
88 TAO_Active_Object_Map_Entry *active_object_map_entry)
90 // Decrement the reference count.
91 CORBA::UShort const new_count = --active_object_map_entry->reference_count_;
93 // Inform the custom servant dispatching (CSD) strategy that the
94 // servant is deactivated. This would be called just once when the
95 // servant is deactivated the first time.
96 if (active_object_map_entry->deactivated_ == 0)
98 this->poa_->servant_deactivated_hook (
99 active_object_map_entry->servant_,
100 active_object_map_entry->user_id_);
103 if (new_count == 0)
105 this->poa_->cleanup_servant (active_object_map_entry->servant_,
106 active_object_map_entry->user_id_);
108 else
110 // It should be noted that there may be a period of time between
111 // an object's deactivation and the etherealization (during
112 // which outstanding requests are being processed) in which
113 // arriving requests on that object should not be passed to its
114 // servant. During this period, requests targeted for such an
115 // object act as if the POA were in holding state until
116 // etherealize completes. If etherealize is called as a
117 // consequence of a deactivate call with a etherealize_objects
118 // parameter of TRUE, incoming requests are rejected.
120 // Else mark entry as closed...
121 active_object_map_entry->deactivated_ = 1;
126 ServantRetentionStrategyRetain::unbind_using_user_id (
127 const PortableServer::ObjectId &user_id)
129 return this->active_object_map_->unbind_using_user_id (user_id);
132 PortableServer::Servant
133 ServantRetentionStrategyRetain::find_servant (
134 const PortableServer::ObjectId &system_id)
136 // Find user id from system id.
137 PortableServer::ObjectId_var user_id;
138 if (active_object_map_->
139 find_user_id_using_system_id (system_id, user_id.out()) != 0)
141 throw ::CORBA::OBJ_ADAPTER ();
144 // This operation returns the active servant associated with the
145 // specified system Object Id value. If the Object Id value is
146 // not active in the POA, an ObjectNotActive exception is
147 // raised.
148 TAO_Active_Object_Map_Entry *entry = 0;
149 PortableServer::Servant servant = 0;
151 int const result =
152 active_object_map_->
153 find_servant_using_system_id_and_user_id (system_id,
154 user_id.in(),
155 servant,
156 entry);
158 if (result == -1)
160 throw PortableServer::POA::ObjectNotActive ();
163 return servant;
166 PortableServer::ObjectId *
167 ServantRetentionStrategyRetain::system_id_to_object_id (
168 const PortableServer::ObjectId &system_id)
170 // The object denoted by the reference does not have to be
171 // active for this operation to succeed.
172 PortableServer::ObjectId_var user_id;
173 if (this->active_object_map_->
174 find_user_id_using_system_id (system_id,
175 user_id.out ()) != 0)
177 throw ::CORBA::OBJ_ADAPTER ();
180 return user_id._retn ();
183 PortableServer::Servant
184 ServantRetentionStrategyRetain::user_id_to_servant (
185 const PortableServer::ObjectId &id)
187 // If the POA has the RETAIN policy and the specified ObjectId is in
188 // the Active Object Map, this operation returns the servant
189 // associated with that object in the Active Object Map.
190 PortableServer::Servant servant = 0;
192 if (this->active_object_map_->find_servant_using_user_id (id, servant) == -1)
194 throw PortableServer::POA::ObjectNotActive ();
197 return servant;
200 CORBA::Object_ptr
201 ServantRetentionStrategyRetain::id_to_reference (
202 const PortableServer::ObjectId &id,
203 bool indirect)
205 // If an object with the specified Object Id value is currently
206 // active, a reference encapsulating the information used to
207 // activate the object is returned.
208 PortableServer::ObjectId_var system_id;
209 PortableServer::Servant servant;
210 CORBA::Short priority;
212 if (this->active_object_map_->
213 find_servant_and_system_id_using_user_id (id,
214 servant,
215 system_id.out (),
216 priority) == 0)
218 // Remember params for potentially invoking <key_to_object> later.
219 this->poa_->key_to_object_params_.set (system_id,
220 servant->_interface_repository_id (),
221 servant,
223 priority,
224 indirect);
226 return this->poa_->invoke_key_to_object_helper_i (servant->_interface_repository_id (),
227 id);
229 else
231 // If the Object Id value is not active in the POA, an
232 // ObjectNotActive exception is raised.
233 throw PortableServer::POA::ObjectNotActive ();
237 TAO_SERVANT_LOCATION
238 ServantRetentionStrategyRetain::servant_present (
239 const PortableServer::ObjectId &system_id,
240 PortableServer::Servant &servant)
242 // Find user id from system id.
243 PortableServer::ObjectId_var user_id;
244 if (this->active_object_map_->
245 find_user_id_using_system_id (system_id, user_id.out()) != 0)
247 throw ::CORBA::OBJ_ADAPTER ();
250 TAO_Active_Object_Map_Entry *entry = 0;
251 int const result = this->active_object_map_->
252 find_servant_using_system_id_and_user_id (system_id,
253 user_id.in(),
254 servant,
255 entry);
256 if (result == 0)
258 // Success
259 return TAO_SERVANT_FOUND;
261 else
263 return TAO_SERVANT_NOT_FOUND;
267 PortableServer::Servant
268 ServantRetentionStrategyRetain::find_servant (
269 const PortableServer::ObjectId &system_id,
270 TAO::Portable_Server::Servant_Upcall &servant_upcall,
271 TAO::Portable_Server::POA_Current_Impl &poa_current_impl)
273 PortableServer::ObjectId user_id;
274 // If we have the RETAIN policy, convert/transform from system id to
275 // user id.
276 if (this->active_object_map_->
277 find_user_id_using_system_id (system_id,
278 user_id) != 0)
280 throw ::CORBA::OBJ_ADAPTER ();
283 poa_current_impl.object_id(user_id);
284 servant_upcall.user_id (&poa_current_impl.object_id());
286 // If the POA has the RETAIN policy, the POA looks in the Active
287 // Object Map to find if there is a servant associated with the
288 // Object Id value from the request. If such a servant exists, the
289 // POA invokes the appropriate method on the servant.
290 PortableServer::Servant servant = 0;
291 TAO_Active_Object_Map_Entry *active_object_map_entry = 0;
292 int const result = this->active_object_map_->
293 find_servant_using_system_id_and_user_id (system_id,
294 user_id,
295 servant,
296 active_object_map_entry);
299 if (result == 0)
301 servant_upcall.active_object_map_entry (active_object_map_entry);
303 // Increment the reference count.
304 servant_upcall.increment_servant_refcount ();
307 return servant;
311 ServantRetentionStrategyRetain::find_servant_priority (
312 const PortableServer::ObjectId &system_id,
313 CORBA::Short &priority)
315 PortableServer::ObjectId user_id;
316 // If we have the RETAIN policy, convert/transform from system id to
317 // user id.
318 if (this->active_object_map_->
319 find_user_id_using_system_id (system_id,
320 user_id) != 0)
322 throw ::CORBA::OBJ_ADAPTER ();
325 // If the POA has the RETAIN policy, the POA looks in the Active
326 // Object Map to find if there is a servant associated with the
327 // Object Id value from the request. If such a servant exists, the
328 // POA invokes the appropriate method on the servant.
329 PortableServer::Servant servant = 0;
330 TAO_Active_Object_Map_Entry *active_object_map_entry = 0;
331 int const result = this->active_object_map_->
332 find_servant_using_system_id_and_user_id (system_id,
333 user_id,
334 servant,
335 active_object_map_entry);
337 if (result == 0)
339 priority = active_object_map_entry->priority_;
340 return 0;
343 return -1;
347 ServantRetentionStrategyRetain::is_servant_in_map (
348 PortableServer::Servant servant,
349 bool &wait_occurred_restart_call)
351 bool deactivated = false;
352 int servant_in_map =
353 this->active_object_map_->is_servant_in_map (servant, deactivated);
355 if (!servant_in_map)
357 return 0;
359 else
361 if (deactivated)
363 if (TAO_debug_level > 0)
364 TAOLIB_DEBUG ((LM_DEBUG,
365 ACE_TEXT ("(%t) TAO_Root_POA::is_servant_in_map: waiting for servant to deactivate\n")));
367 // We are going to wait on this condition variable; the POA
368 // state may change by the time we get the lock again.
369 // Therefore, indicate to the caller that all conditions
370 // need to be checked again.
371 wait_occurred_restart_call = true;
373 ++this->waiting_servant_deactivation_;
375 this->poa_->servant_deactivation_condition ().wait ();
377 --this->waiting_servant_deactivation_;
379 return 0;
381 else
383 return 1;
389 ServantRetentionStrategyRetain::is_user_id_in_map (
390 const PortableServer::ObjectId &id,
391 CORBA::Short priority,
392 bool &priorities_match,
393 bool &wait_occurred_restart_call)
395 bool deactivated = false;
396 bool user_id_in_map =
397 this->active_object_map_->is_user_id_in_map (id,
398 priority,
399 priorities_match,
400 deactivated);
402 if (!user_id_in_map)
404 return 0;
406 else
408 if (deactivated)
410 if (TAO_debug_level > 0)
411 TAOLIB_DEBUG ((LM_DEBUG,
412 ACE_TEXT ("(%t) TAO_Root_POA::is_user_id_in_map: waiting for servant to deactivate\n")));
414 // We are going to wait on this condition variable; the POA
415 // state may change by the time we get the lock again.
416 // Therefore, indicate to the caller that all conditions
417 // need to be checked again.
418 wait_occurred_restart_call = 1;
420 ++this->waiting_servant_deactivation_;
422 this->poa_->servant_deactivation_condition ().wait ();
424 --this->waiting_servant_deactivation_;
426 return 0;
428 else
430 return 1;
435 CORBA::ULong
436 ServantRetentionStrategyRetain::waiting_servant_deactivation () const
438 return waiting_servant_deactivation_;
441 void
442 ServantRetentionStrategyRetain::deactivate_all_objects ()
444 // If the etherealize_objects parameter is TRUE, the POA has the
445 // RETAIN policy, and a servant manager is registered with the POA,
446 // the etherealize operation on the servant manager will be called
447 // for each active object in the Active Object Map. The apparent
448 // destruction of the POA occurs before any calls to etherealize are
449 // made. Thus, for example, an etherealize method that attempts to
450 // invoke operations on the POA will receive the OBJECT_NOT_EXIST
451 // exception.
453 // We must copy the map entries into a separate place since we
454 // cannot remove entries while iterating through the map.
455 ACE_Array_Base<TAO_Active_Object_Map_Entry *> map_entries
456 (this->active_object_map_->current_size ());
458 size_t counter = 0;
459 TAO_Active_Object_Map::user_id_map::iterator end
460 = this->active_object_map_->user_id_map_->end ();
462 for (TAO_Active_Object_Map::user_id_map::iterator iter
463 = this->active_object_map_->user_id_map_->begin ();
464 iter != end;
465 ++iter)
467 TAO_Active_Object_Map::user_id_map::value_type map_pair = *iter;
468 TAO_Active_Object_Map_Entry *active_object_map_entry = map_pair.second ();
470 if (!active_object_map_entry->deactivated_)
472 map_entries[counter] = active_object_map_entry;
473 ++counter;
477 for (size_t i = 0;
478 i < counter;
479 ++i)
481 this->deactivate_map_entry (map_entries[i]);
485 PortableServer::ObjectId *
486 ServantRetentionStrategyRetain::servant_to_user_id (
487 PortableServer::Servant servant)
489 // This operation requires the RETAIN and either the UNIQUE_ID or
490 // IMPLICIT_ACTIVATION policies; if not present, the WrongPolicy
491 // exception is raised.
492 if (!((!this->poa_->allow_multiple_activations ()
493 || this->poa_->allow_implicit_activation ())))
495 throw PortableServer::POA::WrongPolicy ();
499 * If the POA has both the RETAIN and the UNIQUE_ID policy and the
500 * specified servant is active, the Object Id associated with that
501 * servant is returned.
503 * If the POA has both the RETAIN and the IMPLICIT_ACTIVATION policy and
504 * either the POA has the MULTIPLE_ID policy or the specified servant is
505 * not active, the servant is activated using a POA-generated Object Id
506 * and the Interface Id associated with the servant, and that Object Id
507 * is returned.
511 // If the POA has the UNIQUE_ID policy and the specified servant is
512 // active, the Object Id associated with that servant is returned.
513 PortableServer::ObjectId_var user_id;
514 if (!this->poa_->allow_multiple_activations () &&
515 this->active_object_map_->
516 find_user_id_using_servant (servant, user_id.out ()) != -1)
518 return user_id._retn ();
521 // If the POA has the IMPLICIT_ACTIVATION policy and either the POA
522 // has the MULTIPLE_ID policy or the specified servant is not
523 // active, the servant is activated using a POA-generated Object Id
524 // and the Interface Id associated with the servant, and that Object
525 // Id is returned.
526 if (this->poa_->allow_implicit_activation ())
528 // If we reach here, then we either have the MULTIPLE_ID policy
529 // or we have the UNIQUE_ID policy and we are not in the active
530 // object map.
531 PortableServer::ObjectId_var user_id;
532 if (this->active_object_map_->
533 bind_using_system_id_returning_user_id (servant,
534 this->poa_->server_priority (),
535 user_id.out ()) != 0)
537 throw ::CORBA::OBJ_ADAPTER ();
541 // Everything is finally ok
544 // Inform the custom servant dispatching (CSD) strategy that the
545 // sevant is activated.
546 this->poa_->servant_activated_hook (servant, user_id.in ());
548 // ATTENTION: Trick locking here, see class header for details
549 Non_Servant_Upcall non_servant_upcall (*this->poa_);
550 ACE_UNUSED_ARG (non_servant_upcall);
552 // If this operation causes the object to be activated, _add_ref
553 // is invoked at least once on the Servant argument before
554 // returning. Otherwise, the POA does not increment or decrement
555 // the reference count of the Servant passed to this function.
556 servant->_add_ref ();
558 return user_id._retn ();
562 * Otherwise, the ServantNotActive exception is raised.
564 throw PortableServer::POA::ServantNotActive ();
567 PortableServer::ObjectId *
568 ServantRetentionStrategyRetain::servant_to_system_id_i (
569 PortableServer::Servant servant,
570 CORBA::Short &priority)
572 // This operation requires the RETAIN and either the UNIQUE_ID or
573 // IMPLICIT_ACTIVATION policies; if not present, the WrongPolicy
574 // exception is raised.
575 if (!((!this->poa_->allow_multiple_activations ()
576 || this->poa_->allow_implicit_activation ())))
578 throw PortableServer::POA::WrongPolicy ();
581 // This operation has three possible behaviors.
583 // If the POA has the UNIQUE_ID policy and the specified servant is
584 // active, the Object Id associated with that servant is returned.
585 PortableServer::ObjectId_var system_id;
586 if (!this->poa_->allow_multiple_activations () &&
587 this->active_object_map_->
588 find_system_id_using_servant (servant,
589 system_id.out (),
590 priority) != -1)
592 return system_id._retn ();
595 #if defined (CORBA_E_COMPACT) || defined (CORBA_E_MICRO)
596 // CORBA e does not allow implicit activation.
597 // At this point we can throw the WrongPolicy exception.
598 throw PortableServer::POA::WrongPolicy ();
599 #endif /* CORBA_E_COMPACT || CORBA_E_MICRO */
601 // If the POA has the IMPLICIT_ACTIVATION policy and either the POA
602 // has the MULTIPLE_ID policy or the specified servant is not
603 // active, the servant is activated using a POA-generated Object Id
604 // and the Interface Id associated with the servant, and that Object
605 // Id is returned.
606 if (this->poa_->allow_implicit_activation ())
608 // If we reach here, then we either have the MULTIPLE_ID policy
609 // or we have the UNIQUE_ID policy and we are not in the active
610 // object map.
611 PortableServer::ObjectId_var system_id;
612 if (this->active_object_map_->
613 bind_using_system_id_returning_system_id (servant,
614 priority,
615 system_id.out ()) != 0)
617 throw ::CORBA::OBJ_ADAPTER ();
621 // Everything is finally ok
624 // Inform the custom servant dispatching (CSD) strategy that the
625 // sevant is activated.
626 this->poa_->servant_activated_hook (servant, system_id.in ());
628 // ATTENTION: Trick locking here, see class header for details
629 Non_Servant_Upcall non_servant_upcall (*this->poa_);
630 ACE_UNUSED_ARG (non_servant_upcall);
632 // If this operation causes the object to be activated, _add_ref
633 // is invoked at least once on the Servant argument before
634 // returning. Otherwise, the POA does not increment or decrement
635 // the reference count of the Servant passed to this function.
636 servant->_add_ref ();
638 return system_id._retn ();
641 // Otherwise, the ServantNotActive exception is raised.
642 throw PortableServer::POA::ServantNotActive ();
645 CORBA::Object_ptr
646 ServantRetentionStrategyRetain::servant_to_reference (
647 PortableServer::Servant servant)
649 // Note: The allocation of an Object Id value and installation in
650 // the Active Object Map caused by implicit activation may actually
651 // be deferred until an attempt is made to externalize the
652 // reference. The real requirement here is that a reference is
653 // produced that will behave appropriately (that is, yield a
654 // consistent Object Id value when asked politely).
655 CORBA::Short priority = this->poa_->server_priority ();
657 PortableServer::ObjectId_var system_id =
658 this->servant_to_system_id_i (servant, priority);
660 PortableServer::ObjectId user_id;
662 // This operation requires the RETAIN, therefore don't worry about
663 // the NON_RETAIN case.
664 if (this->active_object_map_->
665 find_user_id_using_system_id (system_id.in (), user_id) != 0)
667 throw ::CORBA::OBJ_ADAPTER ();
670 // Remember params for potentially invoking <key_to_object> later.
671 this->poa_->key_to_object_params_.set (
672 system_id,
673 servant->_interface_repository_id (),
674 servant,
676 priority,
677 true);
679 // Ask the ORT to create the object.
680 // @@NOTE:There is a possible deadlock lurking here. We held the
681 // lock, and we are possibly trying to make a call into the
682 // application code. Think what would happen if the app calls us
683 // back. We need to get to this at some point.
684 return this->poa_->invoke_key_to_object_helper_i (
685 servant->_interface_repository_id (), user_id);
688 PortableServer::ObjectId *
689 ServantRetentionStrategyRetain::activate_object (
690 PortableServer::Servant servant,
691 CORBA::Short priority,
692 bool &wait_occurred_restart_call)
694 if (!this->poa_->has_system_id ())
696 throw PortableServer::POA::WrongPolicy ();
699 bool may_activate =
700 this->poa_->is_servant_activation_allowed (servant, wait_occurred_restart_call);
702 if (!may_activate)
704 if (wait_occurred_restart_call)
706 return 0;
708 else
710 throw PortableServer::POA::ServantAlreadyActive ();
714 // Otherwise, the activate_object operation generates an Object Id
715 // and enters the Object Id and the specified servant in the Active
716 // Object Map. The Object Id is returned.
717 PortableServer::ObjectId_var user_id;
718 if (this->active_object_map_->
719 bind_using_system_id_returning_user_id (servant,
720 priority,
721 user_id.out ()) != 0)
723 throw ::CORBA::OBJ_ADAPTER ();
727 // Everything is finally ok
730 // Inform the custom servant dispatching (CSD) strategy that the
731 // sevant is activated.
732 this->poa_->servant_activated_hook (servant, user_id.in ());
734 // ATTENTION: Trick locking here, see class header for details
735 Non_Servant_Upcall non_servant_upcall (*this->poa_);
736 ACE_UNUSED_ARG (non_servant_upcall);
738 // The implementation of activate_object will invoke _add_ref at
739 // least once on the Servant argument before returning. When the POA
740 // no longer needs the Servant, it will invoke _remove_ref on it the
741 // same number of times.
742 servant->_add_ref ();
744 return user_id._retn ();
747 void
748 ServantRetentionStrategyRetain::activate_object_with_id (
749 const PortableServer::ObjectId &id,
750 PortableServer::Servant servant,
751 CORBA::Short priority,
752 bool &wait_occurred_restart_call)
754 // If the POA has the SYSTEM_ID policy and it detects that the
755 // Object Id value was not generated by the system or for this POA,
756 // the activate_object_with_id operation may raise the BAD_PARAM
757 // system exception. An ORB is not required to detect all such
758 // invalid Object Id values, but a portable application must not
759 // invoke activate_object_with_id on a POA that has the SYSTEM_ID
760 // policy with an Object Id value that was not previously generated
761 // by the system for that POA, or, if the POA also has the
762 // PERSISTENT policy, for a previous instantiation of the same POA.
763 if (this->poa_->has_system_id () &&
764 !this->poa_->is_poa_generated_id (id))
766 throw ::CORBA::BAD_PARAM ();
769 // If the CORBA object denoted by the Object Id value is already
770 // active in this POA (there is a servant bound to it in the Active
771 // Object Map), the ObjectAlreadyActive exception is raised.
772 bool priorities_match = true;
773 bool result =
774 this->is_user_id_in_map (id,
775 priority,
776 priorities_match,
777 wait_occurred_restart_call);
779 // @johnny the implementation is not complete, this does the spec also say
780 // If the POA has the UNIQUE_ID policy and the servant is already
781 // in the Active Object Map, the ServantAlreadyActive exception is raised.
782 if (result)
784 throw PortableServer::POA::ObjectAlreadyActive ();
786 else if (wait_occurred_restart_call)
788 // We ended up waiting on a condition variable, the POA state
789 // may have changed while we are waiting. Therefore, we need to
790 // restart this call.
791 return;
794 // If the activate_object_with_id_and_priority operation is invoked
795 // with a different priority to an earlier invocation of one of the
796 // create reference with priority operations, for the same object,
797 // then the ORB shall raise a BAD_INV_ORDER system exception (with a
798 // Standard Minor Exception Code of 1). If the priority value is the
799 // same then the ORB shall return SUCCESS.
800 if (!priorities_match)
802 throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID | 1,
803 CORBA::COMPLETED_NO);
806 bool const may_activate =
807 this->poa_->is_servant_activation_allowed (servant, wait_occurred_restart_call);
809 if (!may_activate)
811 if (wait_occurred_restart_call)
813 return;
815 else
817 throw PortableServer::POA::ServantAlreadyActive ();
821 // Otherwise, the activate_object_with_id operation enters an
822 // association between the specified Object Id and the specified
823 // servant in the Active Object Map.
824 if (this->active_object_map_->bind_using_user_id (servant,
826 priority) != 0)
828 throw ::CORBA::OBJ_ADAPTER ();
832 // Everything is finally ok
835 // Inform the custom servant dispatching (CSD) strategy that the
836 // sevant is activated.
837 this->poa_->servant_activated_hook (servant, id);
839 // ATTENTION: Trick locking here, see class header for details
840 Non_Servant_Upcall non_servant_upcall (*this->poa_);
841 ACE_UNUSED_ARG (non_servant_upcall);
843 // The implementation of activate_object_with_id will invoke
844 // _add_ref at least once on the Servant argument before
845 // returning. When the POA no longer needs the Servant, it will
846 // invoke _remove_ref on it the same number of times.
847 servant->_add_ref ();
850 CORBA::Object_ptr
851 ServantRetentionStrategyRetain::create_reference (
852 const char *intf,
853 CORBA::Short priority)
855 // This operation creates an object reference that encapsulates a
856 // POA-generated Object Id value and the specified interface
857 // repository id. This operation does not cause an activation to
858 // take place. The resulting reference may be passed to clients, so
859 // that subsequent requests on those references will cause the
860 // appropriate servant manager to be invoked, if one is
861 // available. The generated Object Id value may be obtained by
862 // invoking POA::reference_to_id with the created reference.
864 PortableServer::ObjectId_var system_id;
865 PortableServer::ObjectId user_id;
867 if (this->active_object_map_->
868 bind_using_system_id_returning_system_id (0,
869 priority,
870 system_id.out ()) != 0)
872 throw ::CORBA::OBJ_ADAPTER ();
875 // Find user id from system id.
876 if (this->active_object_map_->
877 find_user_id_using_system_id (system_id.in (),
878 user_id) != 0)
880 throw ::CORBA::OBJ_ADAPTER ();
883 // Remember params for potentially invoking <key_to_object> later.
884 this->poa_->key_to_object_params_.set (system_id,
885 intf,
888 priority,
889 true);
891 return this->poa_->invoke_key_to_object_helper_i (intf,
892 user_id);
895 #if !defined (CORBA_E_MICRO)
896 CORBA::Object_ptr
897 ServantRetentionStrategyRetain::create_reference_with_id (
898 const PortableServer::ObjectId &oid,
899 const char *intf,
900 CORBA::Short priority)
902 // This operation creates an object reference that encapsulates the
903 // specified Object Id and interface repository Id values. This
904 // operation does not cause an activation to take place. The
905 // resulting reference may be passed to clients, so that subsequent
906 // requests on those references will cause the object to be
907 // activated if necessary, or the default servant used, depending on
908 // the applicable policies.
910 PortableServer::Servant servant = 0;
911 PortableServer::ObjectId_var system_id;
913 // @@ We need something that can find the system id using
914 // appropriate strategy, at the same time, return the servant if
915 // one is available. Before we have that function,
916 // <create_reference_with_id_i> basically generates broken
917 // collocated object when DIRECT collocation strategy is used.
919 if (this->active_object_map_->
920 find_system_id_using_user_id (oid,
921 priority,
922 system_id.out ()) != 0)
924 throw ::CORBA::OBJ_ADAPTER ();
927 // Remember params for potentially invoking <key_to_object> later.
928 this->poa_->key_to_object_params_.set (system_id,
929 intf,
930 servant,
932 priority,
933 true);
935 return this->poa_->invoke_key_to_object_helper_i (intf, oid);
937 #endif
940 ServantRetentionStrategyRetain::rebind_using_user_id_and_system_id (
941 PortableServer::Servant servant,
942 const PortableServer::ObjectId &user_id,
943 const PortableServer::ObjectId &system_id,
944 TAO::Portable_Server::Servant_Upcall &servant_upcall)
946 TAO_Active_Object_Map_Entry *entry = 0;
947 int result = this->active_object_map_->
948 rebind_using_user_id_and_system_id (servant,
949 user_id,
950 system_id,
951 entry);
952 servant_upcall.active_object_map_entry(entry);
954 return result;
957 CORBA::Boolean
958 ServantRetentionStrategyRetain::servant_has_remaining_activations (
959 PortableServer::Servant servant)
961 return this->active_object_map_->remaining_activations (servant);
965 ::PortableServer::ServantRetentionPolicyValue
966 ServantRetentionStrategyRetain::type() const
968 return ::PortableServer::RETAIN;
971 TAO_Active_Object_Map *
972 ServantRetentionStrategyRetain::get_active_object_map() const
974 return this->active_object_map_.get();
980 TAO_END_VERSIONED_NAMESPACE_DECL