diff options
Diffstat (limited to 'TAO/orbsvcs/orbsvcs/Naming/Hash_Naming_Context.cpp')
-rw-r--r-- | TAO/orbsvcs/orbsvcs/Naming/Hash_Naming_Context.cpp | 606 |
1 files changed, 606 insertions, 0 deletions
diff --git a/TAO/orbsvcs/orbsvcs/Naming/Hash_Naming_Context.cpp b/TAO/orbsvcs/orbsvcs/Naming/Hash_Naming_Context.cpp new file mode 100644 index 00000000000..d8923ac5739 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Naming/Hash_Naming_Context.cpp @@ -0,0 +1,606 @@ +//============================================================================= +/** + * @file Hash_Naming_Context.cpp + * + * $Id$ + * + * @author Marina Spivak <marina@cs.wustl.edu> and Sergio Flores-Gaitan <sergio@cs.wustl.edu> + */ +//============================================================================= + + +#include "orbsvcs/Naming/Hash_Naming_Context.h" +#include "orbsvcs/Naming/nsconf.h" +#include "ace/Auto_Ptr.h" + +ACE_RCSID (Naming, + Hash_Naming_Context, + "$Id$") + + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +// ------------------------------------------------- + +TAO_Bindings_Map::~TAO_Bindings_Map (void) +{ +} + +// ------------------------------------------------- + +TAO_Hash_Naming_Context::TAO_Hash_Naming_Context (PortableServer::POA_ptr poa, + const char *poa_id) + : context_ (0), + interface_ (0), + destroyed_ (0), + poa_ (PortableServer::POA::_duplicate (poa)), + poa_id_ (poa_id) +{ +} + +void +TAO_Hash_Naming_Context::interface (TAO_Naming_Context *i) +{ + this->interface_ = i; +} + +TAO_Hash_Naming_Context::~TAO_Hash_Naming_Context (void) +{ + delete context_; +} + +PortableServer::POA_ptr +TAO_Hash_Naming_Context::_default_POA (void) +{ + return PortableServer::POA::_duplicate (this->poa_.in ()); +} + +CosNaming::NamingContext_ptr +TAO_Hash_Naming_Context::get_context (const CosNaming::Name &name) +{ + // Naming context we will return. + CosNaming::NamingContext_var result = + CosNaming::NamingContext::_nil (); + + // Create compound name to be resolved, i.e., + // (<name> - last component). To avoid copying, we can just reuse + // <name>'s buffer, since we will not be modifying it. + CORBA::ULong name_len = name.length (); + CosNaming::Name comp_name (name.maximum (), + name_len - 1, + const_cast<CosNaming::NameComponent*> (name.get_buffer ())); + try + { + // Resolve the name. + CORBA::Object_var context = resolve (comp_name); + + // Try narrowing object reference to the NamingContext type. + result = CosNaming::NamingContext::_narrow (context.in ()); + } + catch (CosNaming::NamingContext::NotFound& ex) + { + // Add the last component of the name, which was stripped before + // the call to resolve. + CORBA::ULong rest_len = ex.rest_of_name.length () + 1; + ex.rest_of_name.length (rest_len); + ex.rest_of_name[rest_len - 1] = name[name_len - 1]; + + throw; + } + + if (CORBA::is_nil (result.in ())) + { + CosNaming::Name rest; + rest.length (2); + rest[0] = name[name_len - 2]; + rest[1] = name[name_len - 1]; + throw CosNaming::NamingContext::NotFound( + CosNaming::NamingContext::not_context, + rest); + } + // Finally, if everything went smoothly, just return the resolved + // context. + return result._retn (); +} + +void +TAO_Hash_Naming_Context::bind (const CosNaming::Name& n, CORBA::Object_ptr obj) +{ + ACE_GUARD_THROW_EX (TAO_SYNCH_RECURSIVE_MUTEX, + ace_mon, this->lock_, + CORBA::INTERNAL ()); + + // Check to make sure this object didn't have <destroy> method + // invoked on it. + if (this->destroyed_) + throw CORBA::OBJECT_NOT_EXIST (); + + // Get the length of the name. + CORBA::ULong const name_len = n.length (); + + // Check for invalid name. + if (name_len == 0) + throw CosNaming::NamingContext::InvalidName(); + + // If we received compound name, resolve it to get the context in + // which the binding should take place, then perform the binding on + // target context. + if (name_len > 1) + { + CosNaming::NamingContext_var context = this->get_context (n); + + CosNaming::Name simple_name; + simple_name.length (1); + simple_name[0] = n[name_len - 1]; + try + { + context->bind (simple_name, obj); + } + catch (const CORBA::SystemException&) + { + throw CosNaming::NamingContext::CannotProceed( + context.in (), simple_name); + } + } + // If we received a simple name, we need to bind it in this context. + else + { + // Try binding the name. + int result = this->context_->bind (n[0].id, + n[0].kind, + obj, + CosNaming::nobject); + if (result == 1) + throw CosNaming::NamingContext::AlreadyBound(); + + // Something went wrong with the internal structure + else if (result == -1) + throw CORBA::INTERNAL (); + } +} + +void +TAO_Hash_Naming_Context::rebind (const CosNaming::Name& n, + CORBA::Object_ptr obj) +{ + ACE_GUARD_THROW_EX (TAO_SYNCH_RECURSIVE_MUTEX, ace_mon, + this->lock_, + CORBA::INTERNAL ()); + + // Check to make sure this object didn't have <destroy> method + // invoked on it. + if (this->destroyed_) + throw CORBA::OBJECT_NOT_EXIST (); + + // Get the length of the name. + CORBA::ULong const name_len = n.length (); + + // Check for invalid name. + if (name_len == 0) + throw CosNaming::NamingContext::InvalidName(); + + // If we received compound name, resolve it to get the context in + // which the rebinding should take place, then perform the rebinding + // on target context. + if (name_len > 1) + { + CosNaming::NamingContext_var context = get_context (n); + + CosNaming::Name simple_name; + simple_name.length (1); + simple_name[0] = n[name_len - 1]; + try + { + context->rebind (simple_name, obj); + } + catch (const CORBA::SystemException&) + { + throw CosNaming::NamingContext::CannotProceed( + context.in (), simple_name); + } + } + else + // If we received a simple name, we need to rebind it in this + // context. + { + int result = this->context_->rebind (n[0].id, + n[0].kind, + obj, + CosNaming::nobject); + // Check for error conditions. + if (result == -1) + throw CORBA::INTERNAL (); + + else if (result == -2) + throw CosNaming::NamingContext::NotFound( + CosNaming::NamingContext::not_object, n); + } +} + +void +TAO_Hash_Naming_Context::bind_context (const CosNaming::Name &n, + CosNaming::NamingContext_ptr nc) +{ + ACE_GUARD_THROW_EX (TAO_SYNCH_RECURSIVE_MUTEX, ace_mon, + this->lock_, + CORBA::INTERNAL ()); + + // Check to make sure this object didn't have <destroy> method + // invoked on it. + if (this->destroyed_) + throw CORBA::OBJECT_NOT_EXIST (); + + // Do not allow binding of nil context reference. + if (CORBA::is_nil (nc)) + throw CORBA::BAD_PARAM (); + + // Get the length of the name. + CORBA::ULong const name_len = n.length (); + + // Check for invalid name. + if (name_len == 0) + throw CosNaming::NamingContext::InvalidName(); + + // If we received compound name, resolve it to get the context in + // which the binding should take place, then perform the binding on + // target context. + if (name_len > 1) + { + CosNaming::NamingContext_var context = get_context (n); + + CosNaming::Name simple_name; + simple_name.length (1); + simple_name[0] = n[name_len - 1]; + try + { + context->bind_context (simple_name, nc); + } + catch (const CORBA::SystemException&) + { + throw CosNaming::NamingContext::CannotProceed( + context.in (), simple_name); + } + } + // If we received a simple name, we need to bind it in this context. + else + { + // Try binding the name. + int result = this->context_->bind (n[0].id, + n[0].kind, + nc, + CosNaming::ncontext); + if (result == 1) + throw CosNaming::NamingContext::AlreadyBound(); + + // Something went wrong with the internal structure + else if (result == -1) + throw CORBA::INTERNAL (); + } +} + +void +TAO_Hash_Naming_Context::rebind_context (const CosNaming::Name &n, + CosNaming::NamingContext_ptr nc) +{ + ACE_GUARD_THROW_EX (TAO_SYNCH_RECURSIVE_MUTEX, ace_mon, + this->lock_, + CORBA::INTERNAL ()); + + // Check to make sure this object didn't have <destroy> method + // invoked on it. + if (this->destroyed_) + throw CORBA::OBJECT_NOT_EXIST (); + + // Get the length of the name. + CORBA::ULong const name_len = n.length (); + + // Check for invalid name. + if (name_len == 0) + throw CosNaming::NamingContext::InvalidName(); + + // If we received compound name, resolve it to get the context in + // which the rebinding should take place, then perform the rebinding + // on target context. + if (name_len > 1) + { + CosNaming::NamingContext_var context = + get_context (n); + + CosNaming::Name simple_name; + simple_name.length (1); + simple_name[0] = n[name_len - 1]; + try + { + context->rebind_context (simple_name, nc); + } + catch (const CORBA::SystemException&) + { + throw CosNaming::NamingContext::CannotProceed( + context.in (), simple_name); + } + } + else + // If we received a simple name, we need to rebind it in this + // context. + { + int result = this->context_->rebind (n[0].id, + n[0].kind, + nc, + CosNaming::ncontext); + // Check for error conditions. + if (result == -1) + throw CORBA::INTERNAL (); + + else if (result == -2) + throw CosNaming::NamingContext::NotFound( + CosNaming::NamingContext::not_context, + n); + } +} + +CORBA::Object_ptr +TAO_Hash_Naming_Context::resolve (const CosNaming::Name& n) +{ + ACE_GUARD_THROW_EX (TAO_SYNCH_RECURSIVE_MUTEX, ace_mon, this->lock_, + CORBA::INTERNAL ()); + + // Check to make sure this object didn't have <destroy> method + // invoked on it. + if (this->destroyed_) + throw CORBA::OBJECT_NOT_EXIST (); + + // Get the length of the name. + CORBA::ULong const name_len = n.length (); + + // Check for invalid name. + if (name_len == 0) + throw CosNaming::NamingContext::InvalidName(); + + // Resolve the first component of the name. + + // Stores the binding type for the first name component. + CosNaming::BindingType type; + + // Stores the object reference bound to the first name component. + CORBA::Object_var result; + + if (this->context_->find (n[0].id, + n[0].kind, + result.out (), + type) == -1) + throw CosNaming::NamingContext::NotFound( + CosNaming::NamingContext::missing_node, + n); + + // If the name we have to resolve is a compound name, we need to + // resolve it recursively. + if (name_len > 1) + { + CosNaming::NamingContext_var context = + CosNaming::NamingContext::_nil (); + + if (type == CosNaming::ncontext) + { + // Narrow to NamingContext. + context = CosNaming::NamingContext::_narrow (result.in ()); + } + else + // The first name component wasn't bound to a NamingContext. + throw CosNaming::NamingContext::NotFound( + CosNaming::NamingContext::not_context, + n); + + // If narrow failed... + if (CORBA::is_nil (context.in ())) + throw CosNaming::NamingContext::NotFound( + CosNaming::NamingContext::not_context, + n); + else + { + // Successfully resolved the first name component, need to + // recursively call resolve on <n> without the first component. + + // We need a name just like <n> but without the first + // component. Instead of copying data we can reuse <n>'s + // buffer since we will only be using it for 'in' parameters + // (no modifications). + CosNaming::Name rest_of_name + (n.maximum () - 1, + n.length () - 1, + const_cast<CosNaming::NameComponent*> (n.get_buffer ()) + + 1); + + // If there are any exceptions, they will propagate up. + try + { + CORBA::Object_ptr resolved_ref; + resolved_ref = context->resolve (rest_of_name); + return resolved_ref; + } + catch (const CORBA::SystemException&) + { + throw CosNaming::NamingContext::CannotProceed( + context.in (), rest_of_name); + } + } + } + // If the name we had to resolve was simple, we just need to return + // the result. + return result._retn (); +} + +void +TAO_Hash_Naming_Context::unbind (const CosNaming::Name& n) +{ + ACE_GUARD_THROW_EX (TAO_SYNCH_RECURSIVE_MUTEX, ace_mon, + this->lock_, + CORBA::INTERNAL ()); + + // Check to make sure this object didn't have <destroy> method + // invoked on it. + if (this->destroyed_) + throw CORBA::OBJECT_NOT_EXIST (); + + // Get the length of the name. + CORBA::ULong const name_len = n.length (); + + // Check for invalid name. + if (name_len == 0) + throw CosNaming::NamingContext::InvalidName(); + + // If we received compound name, resolve it to get the context in + // which the unbinding should take place, then perform the unbinding + // on target context. + if (name_len > 1) + { + CosNaming::NamingContext_var context = + get_context (n); + + CosNaming::Name simple_name; + simple_name.length (1); + simple_name[0] = n[name_len - 1]; + try + { + context->unbind (simple_name); + } + catch (const CORBA::SystemException&) + { + throw CosNaming::NamingContext::CannotProceed( + context.in (), simple_name); + } + } + // If we received a simple name, we need to unbind it in this + // context. + else + if (this->context_->unbind (n[0].id, + n[0].kind) == -1) + throw CosNaming::NamingContext::NotFound( + CosNaming::NamingContext::missing_node, n); +} + +CosNaming::NamingContext_ptr +TAO_Hash_Naming_Context::bind_new_context (const CosNaming::Name& n) +{ + ACE_GUARD_THROW_EX (TAO_SYNCH_RECURSIVE_MUTEX, + ace_mon, + this->lock_, + CORBA::INTERNAL ()); + + // Check to make sure this object didn't have <destroy> method + // invoked on it. + if (this->destroyed_) + throw CORBA::OBJECT_NOT_EXIST (); + + // Get the length of the name. + CORBA::ULong name_len = n.length (); + + // Check for invalid name. + if (name_len == 0) + throw CosNaming::NamingContext::InvalidName(); + + // If we received compound name, resolve it to get the context in + // which the binding should take place, then perform the operation on + // target context. + if (name_len > 1) + { + CosNaming::NamingContext_var context = + get_context (n); + + CosNaming::Name simple_name; + simple_name.length (1); + simple_name[0] = n[name_len - 1]; + return context->bind_new_context (simple_name); + } + + // If we received a simple name, we need to bind it in this context. + + // Stores our new Naming Context. + CosNaming::NamingContext_var result = + CosNaming::NamingContext::_nil (); + + // Create new context. + result = new_context (); + + // Bind the new context to the name. + try + { + bind_context (n, result.in ()); + } + catch (const CORBA::Exception&) + { + // If the bind() operation fails we must destroy the recently + // created context, should any exceptions be raised by the + // destroy() operation we want to ignore them. + { + try + { + result->destroy (); + } + catch (const CORBA::Exception&) + { + } + } + // Re-raise the exception in bind_context() + throw; + } + return result._retn (); +} + +void +TAO_Hash_Naming_Context::destroy (void) +{ + ACE_GUARD_THROW_EX (TAO_SYNCH_RECURSIVE_MUTEX, + ace_mon, + this->lock_, + CORBA::INTERNAL ()); + + // Check to make sure this object didn't have <destroy> method + // invoked on it. + if (this->destroyed_) + throw CORBA::OBJECT_NOT_EXIST (); + + if (this->context_->current_size () != 0) + throw CosNaming::NamingContext::NotEmpty(); + + // Destroy is a no-op on a root context. + if (root ()) + return; + + else + { + this->destroyed_ = 2; + + // Remove self from POA. Because of reference counting, the POA + // will automatically delete the servant when all pending requests + // on this servant are complete. + + PortableServer::POA_var poa = + this->_default_POA (); + + PortableServer::ObjectId_var id = + PortableServer::string_to_ObjectId (poa_id_.fast_rep ()); + + poa->deactivate_object (id.in ()); + } +} + +int +TAO_Hash_Naming_Context::root (void) +{ + return (ACE_OS::strcmp (this->poa_id_.fast_rep (), + TAO_ROOT_NAMING_CONTEXT) == 0); +} + +int +TAO_Hash_Naming_Context::destroyed (void) +{ + return this->destroyed_; +} + +TAO_Naming_Context * +TAO_Hash_Naming_Context::interface (void) +{ + return this->interface_; +} + +TAO_END_VERSIONED_NAMESPACE_DECL |