diff options
Diffstat (limited to 'TAO/orbsvcs/orbsvcs/LoadBalancing/LB_Redirect_Table.cpp')
-rw-r--r-- | TAO/orbsvcs/orbsvcs/LoadBalancing/LB_Redirect_Table.cpp | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_Redirect_Table.cpp b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_Redirect_Table.cpp new file mode 100644 index 00000000000..9a6b33d519a --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_Redirect_Table.cpp @@ -0,0 +1,180 @@ +// -*- C++ -*- + +#include "LB_Redirect_Table.h" +#include "Object.h" +#include "Exception.h" +#include "Environment.h" +#include "CORBA_String.h" +#include "debug.h" + +ACE_RCSID (LoadBalancing, + LB_Redirect_Table, + "$Id$") + +// **************************************************************** + +TAO_LB_Redirect_Table::TAO_LB_Redirect_Table (void) + : table_ () +{ +} + +TAO_LB_Redirect_Table::~TAO_LB_Redirect_Table (void) +{ + // Must explicitly call destroy() in the destructor since not all + // applications will invoke ORB::shutdown() or ORB::destroy(). + this->destroy (); +} + +void +TAO_LB_Redirect_Table::register_redirect ( + const char *type_id, + CORBA::Object_ptr redirect_to, + CORBA::Environment &ACE_TRY_ENV) +{ + // The RepositoryId should never be zero since it is not possible to + // send a NULL string as an "in" argument. + if (ACE_OS_String::strlen (id) == 0) + ACE_THROW (CORBA::BAD_PARAM ()); + + if (CORBA::is_nil (obj)) + ACE_THROW (CORBA::BAD_PARAM ()); + + int result = this->bind (type_id, redirect_to); + + if (result == 1) + { + if (TAO_debug_level > 1) + ACE_ERROR ((LM_ERROR, + "(%P|%t) LB_Redirect_Table::register_redirect:\n" + " Could not register duplicate object <%s> with " + "the LB_Redirect_Table\n", + type_id)); + + ACE_THROW (CORBA::INV_OBJREF ()); + } + + if (result == -1) + { + if (TAO_debug_level > 1) + ACE_ERROR ((LM_ERROR, + "(%P|%t) LB_Redirect_Table::register_redirect:\n" + " Could not register redirect object <%s> with " + "the LB_Redirect_Table\n", + type_id)); + + ACE_THROW (CORBA::INTERNAL ()); + } +} + +void +TAO_LB_Redirect_Table::find_redirect ( + PortableInterceptor::ServerRequestInfo_ptr ri, + CORBA::Environment &ACE_TRY_ENV) +{ + // This could become very slow if there are many type of targets + // being redirected since we're doing a linear search using string + // comparisons. + // + // We do things this way to avoid the memory allocation that would + // occur if we were to just use the + // ServerRequestInfo::target_most_derived_interface() method. At + // some point, there is a threshold reached where the cost of the + // iteration through the redirect table is more expensive than the + // allocation incurred by calling + // ServerRequestInfo::target_most_derived_interface(). That + // threshold is approached as the number of redirects in the table + // becomes "large." For now, we optimize for the common case and + // assume that only a few types of targets (i.e. objects/servants + // with different RepositoryIds) exist at the current location. + // + // Note that if no redirects are registered, then this method + // basically becomes a no-op. + + for (Table::iterator i = this->table_.begin (); + i != this->table_.end (); + ++i) + { + // Compare the target's RepositoryId with the registered + // redirects. + CORBA::Boolean matched = + ri->target_is_a ((*i).ext_id_, ACE_TRY_ENV); + ACE_CHECK_RETURN (0); + + if (matched) + ACE_THROW (PortableInterceptor::ForwardRequest ( + (*i).int_id_, + 0 /* non-permanent forward */)); + } +} + +int +TAO_LB_Redirect_Table::remove_redirect (const char *type_id, + CORBA::Environment &ACE_TRY_ENV) +{ + Table::ENTRY *entry = 0; + + int result = this->table_.find (type_id, entry); + + if (result == 0) + { + // Deallocate the external ID and obtain the ORB core pointer + // before unbinding the entry since the entry is deallocated + // during the call to unbind(). + CORBA::string_free (ACE_const_cast (char *, entry->ext_id_)); + CORBA::Object_ptr redirect = entry->int_id_; + + result = this->table_.unbind (entry); + + if (result != 0) + return result; + + CORBA::release (redirect); + } + + return result; +} + +void +TAO_LB_Redirect_Table::destroy (void) +{ + for (Table::iterator i = this->table_.begin (); + i != this->table_.end (); + ++i) + { + // Deallocate the id. + CORBA::string_free (ACE_const_cast (char *, (*i).ext_id_)); + + // Release the Object. + CORBA::release ((*i).int_id_); + } + + this->table_.unbind_all (); +} + +int +TAO_LB_Redirect_Table::bind (const char *id, + CORBA::Object_ptr obj) +{ + // Make sure that the supplied Object reference is valid, + // i.e. not nil. + if (id == 0 || CORBA::is_nil (obj)) + { + errno = EINVAL; + return -1; + }; + + CORBA::String_var type_id = CORBA::string_dup (id); + CORBA::Object_var redirect = CORBA::Object::_duplicate (obj); + + int result = this->table_.bind (type_id.in (), + redirect.in ()); + + if (result == 0) + { + // Transfer ownership to the Object Table. + (void) type_id._retn (); + (void) redirect._retn (); + } + + return result; +} |