#include "Storable_Naming_Context.h" #include "Bindings_Iterator_T.h" #include // The following #pragma is needed to disable a warning that occurs // in MSVC 6 due to the overly long debugging symbols generated for // the ACE_Auto_Basic_Ptr > template // instance used by some of the methods in this file. #ifdef _MSC_VER # pragma warning(disable: 4786) /* identifier was truncated to '255' characters in the browser information */ #endif /* _MSC_VER */ #include "ace/Auto_Ptr.h" #include "ace/OS_NS_stdio.h" const char * TAO_Storable_Naming_Context::root_name_; ACE_UINT32 TAO_Storable_Naming_Context::gcounter_; ACE_Auto_Ptr TAO_Storable_Naming_Context::gfl_; int TAO_Storable_Naming_Context::redundant_; ACE_RCSID (Naming, Storable_Naming_Context, "$Id$") TAO_Storable_IntId::TAO_Storable_IntId (void) : ref_ (""), type_ (CosNaming::nobject) { } TAO_Storable_IntId::TAO_Storable_IntId (const char * ior, CosNaming::BindingType type) : ref_ (ior), type_ (type) { } TAO_Storable_IntId::TAO_Storable_IntId (const TAO_Storable_IntId &rhs) { ref_ = rhs.ref_; type_ = rhs.type_; } TAO_Storable_IntId::~TAO_Storable_IntId (void) { } void TAO_Storable_IntId::operator= (const TAO_Storable_IntId &rhs) { // check for self assignment. if (&rhs == this) return; type_ = rhs.type_; ref_ = rhs.ref_; } TAO_Storable_ExtId::TAO_Storable_ExtId (void) : id_ (""), kind_ ("") { } TAO_Storable_ExtId::TAO_Storable_ExtId (const char *id, const char *kind) : id_ (id) , kind_ (kind) { } TAO_Storable_ExtId::TAO_Storable_ExtId (const TAO_Storable_ExtId &rhs) { id_ = rhs.id_; kind_ = rhs.kind_; } TAO_Storable_ExtId::~TAO_Storable_ExtId (void) { } void TAO_Storable_ExtId::operator= (const TAO_Storable_ExtId &rhs) { // Check for self assignment. if (&rhs == this) return; id_ = rhs.id_; kind_ = rhs.kind_; } bool TAO_Storable_ExtId::operator== (const TAO_Storable_ExtId &rhs) const { return (ACE_OS::strcmp (id_.in(), rhs.id_.in()) == 0) && (ACE_OS::strcmp (kind_.in(), rhs.kind_.in()) == 0); } bool TAO_Storable_ExtId::operator!= (const TAO_Storable_ExtId &rhs) const { return (ACE_OS::strcmp (id_.in(), rhs.id_.in()) != 0) || (ACE_OS::strcmp (kind_.in(), rhs.kind_.in()) != 0); } u_long TAO_Storable_ExtId::hash (void) const { // @CJC I wager this could be optimized a bit better, but I'm not // sure how much it's called. At the very least, we could allocate // just one ACE_CString, and copy id_ and kind_ into that, rather than // taking a double-hit on allocations. ACE_CString temp (id_.in()); temp += kind_.in(); return temp.hash (); } const char * TAO_Storable_ExtId::id (void) { return id_.in(); } const char * TAO_Storable_ExtId::kind (void) { return kind_.in(); } int TAO_Storable_Bindings_Map::unbind (const char *id, const char *kind) { ACE_TRACE("unbind"); TAO_Storable_ExtId name (id, kind); return this->map_.unbind (name); } int TAO_Storable_Bindings_Map::bind (const char *id, const char *kind, CORBA::Object_ptr obj, CosNaming::BindingType type) { ACE_TRACE("bind"); return this->shared_bind (id, kind, obj, type, 0); } int TAO_Storable_Bindings_Map::rebind (const char *id, const char *kind, CORBA::Object_ptr obj, CosNaming::BindingType type) { ACE_TRACE("rebind"); return this->shared_bind (id, kind, obj, type, 1); } int TAO_Storable_Bindings_Map::find (const char *id, const char *kind, CORBA::Object_ptr & obj, CosNaming::BindingType &type) { ACE_TRACE("find"); TAO_Storable_ExtId name (id, kind); TAO_Storable_IntId entry; if (this->map_.find (name, entry) != 0) { return -1; } else { ACE_DECLARE_NEW_CORBA_ENV; obj = orb_->string_to_object (entry.ref_.in() ACE_ENV_ARG_PARAMETER); ACE_CHECK_RETURN (-1); type = entry.type_; return 0; } } TAO_Storable_Bindings_Map::TAO_Storable_Bindings_Map (size_t hash_table_size, CORBA::ORB_ptr orb) : map_ (hash_table_size), orb_(CORBA::ORB::_duplicate (orb)) { ACE_TRACE("TAO_Storable_Bindings_Map"); } TAO_Storable_Bindings_Map::~TAO_Storable_Bindings_Map (void) { ACE_TRACE("~TAO_Storable_Bindings_Map"); } TAO_Storable_Bindings_Map::HASH_MAP & TAO_Storable_Bindings_Map::map (void) { ACE_TRACE("map"); return map_; } size_t TAO_Storable_Bindings_Map::current_size (void) { ACE_TRACE("current_size"); return map_.current_size (); } size_t TAO_Storable_Bindings_Map::total_size (void) { ACE_TRACE("total_size"); return map_.total_size (); } int TAO_Storable_Bindings_Map::shared_bind (const char * id, const char * kind, CORBA::Object_ptr obj, CosNaming::BindingType type, int rebind) { ACE_TRACE("shared_bind"); TAO_Storable_ExtId new_name (id, kind); CORBA::String_var ior = orb_->object_to_string(obj); TAO_Storable_IntId new_entry (ior.in(), type); TAO_Storable_IntId old_entry; if (rebind == 0) { // Do a normal bind. return this->map_.bind (new_name, new_entry); } else // Rebind. { // Check that types of old and new entries match. if (this->map_.find (new_name, old_entry) == 0 && type != old_entry.type_) return -2; else return this->map_.rebind (new_name, new_entry); } } void TAO_Storable_Naming_Context::Write(TAO_Storable_Base& wrtr) { ACE_TRACE("Write"); TAO_NS_Persistence_Header header; header.size (ACE_static_cast(unsigned int, storable_context_->current_size())); header.destroyed (destroyed_); wrtr << header; if( storable_context_->current_size() == 0 ) return; ACE_Hash_Map_Iterator it = storable_context_->map().begin(); ACE_Hash_Map_Iterator itend = storable_context_->map().end(); ACE_Hash_Map_Entry ent = *it; while (!(it == itend)) { TAO_NS_Persistence_Record record; CosNaming::BindingType bt = (*it).int_id_.type_; if (bt == CosNaming::ncontext) record.type(TAO_NS_Persistence_Record::NCONTEXT); else if (bt == CosNaming::nobject) record.type(TAO_NS_Persistence_Record::OBJREF); //else //there shouldn't be any other, can there be ?? //ignore for now // todo - are we using this i ?? //int i = storable_context_->current_size(); const char *myid = (*it).ext_id_.id(); ACE_CString id(myid); record.id(id); const char *mykind = (*it).ext_id_.kind(); ACE_CString kind(mykind); record.kind(kind); ACE_CString name; if (bt == CosNaming::nobject) { name.set((*it).int_id_.ref_.in()); } else { CORBA::Object_var obj = orb_->string_to_object((*it).int_id_.ref_.in()); PortableServer::ObjectId_var oid = poa_->reference_to_id(obj.in()); CORBA::String_var nm = PortableServer::ObjectId_to_string(oid.in()); const char *newname = nm.in(); name.set(newname); } record.ref(name); wrtr << record; it.advance(); } } // Helper function to load a new context into the binding_map int TAO_Storable_Naming_Context::load_map(File_Open_Lock_and_Check *flck ACE_ENV_ARG_DECL) { ACE_TRACE("load_map"); // assume file already open for reading TAO_Storable_Bindings_Map *bindings_map; // create the new bindings map ACE_NEW_THROW_EX (bindings_map, TAO_Storable_Bindings_Map (hash_table_size_,orb_.in()), CORBA::NO_MEMORY ()); // get the data for this bindings map from the file TAO_NS_Persistence_Header header; TAO_NS_Persistence_Record record; // we are only using the size from this header flck->peer() >> header; // reset the destroyed flag this->destroyed_ = header.destroyed(); // read in the data for the map for (unsigned int i=0; ipeer() >> record; if( record.type() == TAO_NS_Persistence_Record::NCONTEXT ) { PortableServer::ObjectId_var id = PortableServer::string_to_ObjectId(record.ref().c_str()); const char * intf = interface_->_interface_repository_id(); CORBA::Object_var objref = poa_->create_reference_with_id ( id.in (), intf ); bindings_map->bind( record.id().c_str(), record.kind().c_str(), objref.in(), CosNaming::ncontext ); } else { CORBA::Object_var objref = orb_->string_to_object (record.ref().c_str()); bindings_map->bind( record.id().c_str(), record.kind().c_str(), objref.in(), CosNaming::nobject ); } } storable_context_ = bindings_map; context_ = storable_context_; return 0; } TAO_Storable_Naming_Context:: File_Open_Lock_and_Check::File_Open_Lock_and_Check( TAO_Storable_Naming_Context * context, const char * mode ACE_ENV_ARG_DECL) :closed_(1), context_(context) { ACE_TRACE("File_Open_Lock_and_Check"); // We only accept a subset of mode argument, check it rwflags_ = 0; for( unsigned int i = 0; ipersistence_directory_); file_name += "/"; file_name += context->name_; // Create the stream fl_ = context->factory_->create_stream(file_name, ACE_TEXT_CHAR_TO_TCHAR(mode)); if (TAO_Storable_Naming_Context::redundant_) { if (fl_->open() != 0) { delete fl_; ACE_THROW(CORBA::PERSIST_STORE()); } // acquire a lock on it if (fl_ -> flock(0, 0, 0) != 0) { fl_->close(); delete fl_; ACE_THROW(CORBA::INTERNAL()); } // now that the file is successfully opened and locked it must be // unlocked/closed before we leave this class closed_ = 0; if ( ! (rwflags_ & mode_create) ) { // Check if our copy is up to date time_t new_last_changed = fl_->last_changed(); if( new_last_changed > context->last_changed_ ) { context->last_changed_ = new_last_changed; // Throw our map away delete context->storable_context_; // and build a new one from disk context->load_map(this ACE_ENV_ARG_PARAMETER); ACE_CHECK; } } } else if ( ! context->storable_context_ || (rwflags_ & mode_write) ) { if (fl_->open() != 0) { delete fl_; ACE_THROW(CORBA::PERSIST_STORE()); } // now that the file is successfully opened // unlocked/closed before we leave this class closed_ = 0; if(!context->storable_context_) { // Load the map from disk context->load_map(this ACE_ENV_ARG_PARAMETER); ACE_CHECK; } } else { // Need to insure that fl_ gets deleted delete fl_; } } void TAO_Storable_Naming_Context:: File_Open_Lock_and_Check::release(void) { ACE_TRACE("release"); if ( ! closed_ ) { // If we updated the disk, save the time stamp if(TAO_Storable_Naming_Context::redundant_) { if( rwflags_ & mode_write ) context_->last_changed_ = fl_->last_changed(); fl_->funlock(0, 0, 0); } fl_->close(); delete fl_; closed_ = 1; } } TAO_Storable_Naming_Context:: File_Open_Lock_and_Check::~File_Open_Lock_and_Check(void) { ACE_TRACE("~File_Open_Lock_and_Check"); this->release(); } TAO_Storable_Base & TAO_Storable_Naming_Context:: File_Open_Lock_and_Check::peer(void) { ACE_TRACE("peer"); return *fl_; } TAO_Storable_Naming_Context::TAO_Storable_Naming_Context ( CORBA::ORB_ptr orb, PortableServer::POA_ptr poa, const char *poa_id, TAO_Naming_Service_Persistence_Factory *factory, const ACE_TCHAR *persistence_directory, size_t hash_table_size) : TAO_Hash_Naming_Context (poa, poa_id), counter_ (0), storable_context_ (0), orb_(CORBA::ORB::_duplicate (orb)), name_ (poa_id), poa_ (PortableServer::POA::_duplicate (poa)), factory_(factory), persistence_directory_ (ACE_TEXT_ALWAYS_CHAR(persistence_directory)), hash_table_size_(hash_table_size), last_changed_(0) { ACE_TRACE("TAO_Storable_Naming_Context"); } TAO_Storable_Naming_Context::~TAO_Storable_Naming_Context (void) { ACE_TRACE("~TAO_Storable_Naming_Context"); // If we're in the DTOR as a result of the destroy() operation, // then we go ahead and delete the file. Otherwise, we leave the // file around because they need to be there for persistence. if (this->destroyed_) { // Make sure we delete the associated stream ACE_CString file_name (this->persistence_directory_); file_name += "/"; file_name += this->name_; // Now delete the file ACE_Auto_Ptr fl ( this->factory_->create_stream(ACE_TEXT_ALWAYS_CHAR(file_name.c_str()), ACE_TEXT("r")) ); if (fl.get()) { if (TAO_debug_level > 5) ACE_DEBUG ((LM_DEBUG, "(%P|%t) NameService: removing file %s\n", file_name.fast_rep())); fl->remove (); } } } CosNaming::NamingContext_ptr TAO_Storable_Naming_Context::make_new_context ( CORBA::ORB_ptr orb, PortableServer::POA_ptr poa, const char *poa_id, size_t context_size, TAO_Naming_Service_Persistence_Factory *factory, const ACE_TCHAR *persistence_directory, TAO_Storable_Naming_Context **new_context ACE_ENV_ARG_DECL) { ACE_TRACE("make_new_context"); // Store the stub we will return here. CosNaming::NamingContext_var result; // Put together a servant for the new Naming Context. TAO_Storable_Naming_Context *context_impl = 0; ACE_NEW_THROW_EX (context_impl, TAO_Storable_Naming_Context (orb, poa, poa_id, factory, persistence_directory, context_size), CORBA::NO_MEMORY ()); ACE_CHECK_RETURN (result._retn ()); // Put into the auto pointer temporarily, in case next // allocation fails. ACE_Auto_Basic_Ptr temp (context_impl); TAO_Naming_Context *context = 0; ACE_NEW_THROW_EX (context, TAO_Naming_Context (context_impl), CORBA::NO_MEMORY ()); ACE_CHECK_RETURN (result._retn ()); // Let know about it's . context_impl->interface (context); // Release auto pointer, and start using reference counting to // control our servant. temp.release (); PortableServer::ServantBase_var s = context; // Register the new context with the POA. PortableServer::ObjectId_var id = PortableServer::string_to_ObjectId (poa_id); // If we try to register a naming context that is already registered, // the following activation causes a POA::ObjectAlreadyActive exception be // thrown which is transmitted as a CORBA::UNKNOWN on the wire. To rectify // this problem, we explicitly throw the correct INS exception in // this situation. ACE_TRY { poa->activate_object_with_id (id.in (), context ACE_ENV_ARG_PARAMETER); ACE_TRY_CHECK; } ACE_CATCH (PortableServer::POA::ObjectAlreadyActive, ex) { ACE_THROW_RETURN (CosNaming::NamingContext::AlreadyBound(), CosNaming::NamingContext::_nil ()); } ACE_ENDTRY; ACE_CHECK_RETURN (result._retn ()); result = context->_this (ACE_ENV_SINGLE_ARG_PARAMETER); ACE_CHECK_RETURN (CosNaming::NamingContext::_nil ()); // return the address of the new context object so that caller can finish *new_context = context_impl; return result._retn (); } CosNaming::NamingContext_ptr TAO_Storable_Naming_Context::new_context (ACE_ENV_SINGLE_ARG_DECL) { ACE_TRACE("new_context"); ACE_GUARD_THROW_EX (ACE_SYNCH_RECURSIVE_MUTEX, ace_mon, this->lock_, CORBA::INTERNAL ()); ACE_CHECK_RETURN (CosNaming::NamingContext::_nil ()); { // Open the backing file File_Open_Lock_and_Check flck(this, "r" ACE_ENV_ARG_PARAMETER); ACE_CHECK_RETURN (CosNaming::NamingContext::_nil ()); // Check to make sure this object didn't have method // invoked on it. if (this->destroyed_) ACE_THROW_RETURN (CORBA::OBJECT_NOT_EXIST (), CosNaming::NamingContext::_nil ()); } TAO_NS_Persistence_Global global; // Generate a POA id for the new context. if(redundant_) { // acquire a lock on the file that holds our counter if (gfl_->open() != 0) { delete gfl_.release(); ACE_THROW_RETURN(CORBA::PERSIST_STORE(), CosNaming::NamingContext::_nil ()); } if (gfl_ -> flock(0, 0, 0) != 0) ACE_THROW_RETURN (CORBA::INTERNAL(), CosNaming::NamingContext::_nil ()); // get the counter from disk *gfl_.get() >> global; gcounter_ = global.counter(); // use it to generate a new name } char poa_id[BUFSIZ]; ACE_OS::sprintf (poa_id, "%s_%d", root_name_, gcounter_++); // then save it back on disk global.counter(gcounter_); *gfl_.get() << global; if(redundant_) { // and release our lock if (gfl_ -> flock(0, 0, 0) != 0) ACE_THROW_RETURN(CORBA::INTERNAL(), CosNaming::NamingContext::_nil ()); gfl_->close(); } // Create a new context. TAO_Storable_Naming_Context *new_context = 0; CosNaming::NamingContext_var result = make_new_context (this->orb_.in (), this->poa_.in (), poa_id, this->storable_context_->total_size (), this->factory_, ACE_TEXT_CHAR_TO_TCHAR (this->persistence_directory_.c_str ()), &new_context ACE_ENV_ARG_PARAMETER); ACE_CHECK_RETURN (CosNaming::NamingContext::_nil ()); // Since this is a new context, make an empty map in it ACE_NEW_THROW_EX (new_context->storable_context_, TAO_Storable_Bindings_Map (hash_table_size_,orb_.in ()), CORBA::NO_MEMORY ()); ACE_CHECK_RETURN (CosNaming::NamingContext::_nil ()); new_context->context_ = new_context->storable_context_; File_Open_Lock_and_Check flck(new_context, "wc" ACE_ENV_ARG_PARAMETER); ACE_CHECK_RETURN (CosNaming::NamingContext::_nil ()); new_context->Write(flck.peer()); return result._retn (); } void TAO_Storable_Naming_Context::rebind (const CosNaming::Name& n, CORBA::Object_ptr obj ACE_ENV_ARG_DECL) { ACE_TRACE("rebind"); // Get the length of the name. CORBA::ULong name_len = n.length (); // Check for invalid name. if (name_len == 0) ACE_THROW (CosNaming::NamingContext::InvalidName()); // we didn't need a lock to check the input arg, but now we do ACE_GUARD_THROW_EX (ACE_SYNCH_RECURSIVE_MUTEX, ace_mon, this->lock_, CORBA::INTERNAL ()); ACE_CHECK; // Open the backing file File_Open_Lock_and_Check flck(this, name_len > 1 ? "r" : "rw" ACE_ENV_ARG_PARAMETER); ACE_CHECK; // Check to make sure this object didn't have method // invoked on it. if (this->destroyed_) ACE_THROW (CORBA::OBJECT_NOT_EXIST ()); // 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) { // This had been a read on the file so now we are done with it flck.release(); CosNaming::NamingContext_var context = get_context (n ACE_ENV_ARG_PARAMETER); ACE_CHECK; CosNaming::Name simple_name; simple_name.length (1); simple_name[0] = n[name_len - 1]; context->rebind (simple_name, obj ACE_ENV_ARG_PARAMETER); ACE_CHECK; } // If we received a simple name, we need to rebind it in this // context. else { int result = this->context_->rebind (n[0].id, n[0].kind, obj, CosNaming::nobject); // Check for error conditions. if (result == -1) ACE_THROW (CORBA::INTERNAL ()); else if (result == -2) ACE_THROW (CosNaming::NamingContext::NotFound (CosNaming::NamingContext::not_object, n)); this->Write(flck.peer()); } } void TAO_Storable_Naming_Context::bind_context (const CosNaming::Name &n, CosNaming::NamingContext_ptr nc ACE_ENV_ARG_DECL) { ACE_TRACE("TAO_Storable_Naming_Context::bind_context"); // Get the length of the name. CORBA::ULong name_len = n.length (); // Check for invalid name. if (name_len == 0) ACE_THROW (CosNaming::NamingContext::InvalidName()); // Do not allow binding of nil context reference. if (CORBA::is_nil (nc)) ACE_THROW (CORBA::BAD_PARAM ()); // we didn't need a lock to check the input arg, but now we do ACE_GUARD_THROW_EX (ACE_SYNCH_RECURSIVE_MUTEX, ace_mon, this->lock_, CORBA::INTERNAL ()); ACE_CHECK; // Open the backing file File_Open_Lock_and_Check flck(this, name_len > 1 ? "r" : "rw" ACE_ENV_ARG_PARAMETER); ACE_CHECK; // Check to make sure this object didn't have method // invoked on it. if (this->destroyed_) ACE_THROW (CORBA::OBJECT_NOT_EXIST ()); // 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) { // This had been a read on the file so now we are done with it flck.release(); CosNaming::NamingContext_var context = get_context (n ACE_ENV_ARG_PARAMETER); ACE_CHECK; CosNaming::Name simple_name; simple_name.length (1); simple_name[0] = n[name_len - 1]; context->bind_context (simple_name, nc ACE_ENV_ARG_PARAMETER); ACE_CHECK; } // 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) ACE_THROW (CosNaming::NamingContext::AlreadyBound()); // Something went wrong with the internal structure else if (result == -1) ACE_THROW (CORBA::INTERNAL ()); this->Write(flck.peer()); } } void TAO_Storable_Naming_Context::rebind_context (const CosNaming::Name &n, CosNaming::NamingContext_ptr nc ACE_ENV_ARG_DECL) { ACE_TRACE("rebind_context"); // Get the length of the name. CORBA::ULong name_len = n.length (); // Check for invalid name. if (name_len == 0) ACE_THROW (CosNaming::NamingContext::InvalidName()); // we didn't need a lock to check the input arg, but now we do ACE_GUARD_THROW_EX (ACE_SYNCH_RECURSIVE_MUTEX, ace_mon, this->lock_, CORBA::INTERNAL ()); ACE_CHECK; // Open the backing file File_Open_Lock_and_Check flck(this, name_len > 1 ? "r" : "rw" ACE_ENV_ARG_PARAMETER); ACE_CHECK; // Check to make sure this object didn't have method // invoked on it. if (this->destroyed_) ACE_THROW (CORBA::OBJECT_NOT_EXIST ()); // 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) { // This had been a read on the file so now we are done with it flck.release(); CosNaming::NamingContext_var context = get_context (n ACE_ENV_ARG_PARAMETER); ACE_CHECK; CosNaming::Name simple_name; simple_name.length (1); simple_name[0] = n[name_len - 1]; context->rebind_context (simple_name, nc ACE_ENV_ARG_PARAMETER); ACE_CHECK; } // If we received a simple name, we need to rebind it in this // context. else { int result = this->context_->rebind (n[0].id, n[0].kind, nc, CosNaming::ncontext); // Check for error conditions. if (result == -1) ACE_THROW (CORBA::INTERNAL ()); else if (result == -2) ACE_THROW (CosNaming::NamingContext::NotFound (CosNaming::NamingContext::not_context, n)); this->Write(flck.peer()); } } CORBA::Object_ptr TAO_Storable_Naming_Context::resolve (const CosNaming::Name& n ACE_ENV_ARG_DECL) { ACE_TRACE("resolve"); // Get the length of the name. CORBA::ULong name_len = n.length (); // Check for invalid name. if (name_len == 0) ACE_THROW_RETURN (CosNaming::NamingContext::InvalidName(), CORBA::Object::_nil ()); // we didn't need a lock to check the input arg, but now we do ACE_GUARD_THROW_EX (ACE_SYNCH_RECURSIVE_MUTEX, ace_mon, this->lock_, CORBA::INTERNAL ()); ACE_CHECK_RETURN (CORBA::Object::_nil ()); // Open the backing file File_Open_Lock_and_Check flck(this, "r" ACE_ENV_ARG_PARAMETER); ACE_CHECK_RETURN (CORBA::Object::_nil ()); // Check to make sure this object didn't have method // invoked on it. if (this->destroyed_) ACE_THROW_RETURN (CORBA::OBJECT_NOT_EXIST (), CORBA::Object::_nil ()); // Resolve the first component of the name. flck.release(); // Stores the binding type for the first name component. CosNaming::BindingType type; // Stores the object reference bound to the first name component. CORBA::Object_ptr obj = CORBA::Object::_nil (); if (this->context_->find (n[0].id, n[0].kind, obj, type) == -1) ACE_THROW_RETURN (CosNaming::NamingContext::NotFound (CosNaming::NamingContext::missing_node, n), CORBA::Object::_nil ()); // Store the value in var to avoid memory leaks. CORBA::Object_var result = obj; // 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 () ACE_ENV_ARG_PARAMETER); ACE_CHECK_RETURN (result._retn ()); } else // The first name component wasn't bound to a NamingContext. ACE_THROW_RETURN (CosNaming::NamingContext::NotFound (CosNaming::NamingContext::not_context, n), CORBA::Object::_nil ()); // If narrow failed... if (CORBA::is_nil (context.in ())) ACE_THROW_RETURN (CosNaming::NamingContext::NotFound (CosNaming::NamingContext::not_context, n), CORBA::Object::_nil ()); else { // Successfully resolved the first name component, need to // recursively call resolve on without the first component. // We need a name just like but without the first // component. Instead of copying data we can reuse '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, ACE_const_cast (CosNaming::NameComponent*, n.get_buffer ()) + 1); // If there are any exceptions, they will propagate up. return context->resolve (rest_of_name ACE_ENV_ARG_PARAMETER); } } // If the name we had to resolve was simple, we just need to return // the result. return result._retn (); } void TAO_Storable_Naming_Context::unbind (const CosNaming::Name& n ACE_ENV_ARG_DECL) { ACE_TRACE("unbind"); // Get the length of the name. CORBA::ULong name_len = n.length (); // Check for invalid name. if (name_len == 0) ACE_THROW (CosNaming::NamingContext::InvalidName()); // we didn't need a lock to check the input arg, but now we do ACE_GUARD_THROW_EX (ACE_SYNCH_RECURSIVE_MUTEX, ace_mon, this->lock_, CORBA::INTERNAL ()); ACE_CHECK; // Open the backing file File_Open_Lock_and_Check flck(this, name_len > 1 ? "r" : "rw" ACE_ENV_ARG_PARAMETER); ACE_CHECK; // Check to make sure this object didn't have method // invoked on it. if (this->destroyed_) ACE_THROW (CORBA::OBJECT_NOT_EXIST ()); // 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) { // This had been a read on the file so now we are done with it flck.release(); CosNaming::NamingContext_var context = get_context (n ACE_ENV_ARG_PARAMETER); ACE_CHECK; CosNaming::Name simple_name; simple_name.length (1); simple_name[0] = n[name_len - 1]; context->unbind (simple_name ACE_ENV_ARG_PARAMETER); ACE_CHECK; } // 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) ACE_THROW (CosNaming::NamingContext::NotFound (CosNaming::NamingContext::missing_node, n)); this->Write(flck.peer()); } } CosNaming::NamingContext_ptr TAO_Storable_Naming_Context::bind_new_context (const CosNaming::Name& n ACE_ENV_ARG_DECL) { ACE_TRACE("bind_new_context"); // Get the length of the name. CORBA::ULong name_len = n.length (); // Check for invalid name. if (name_len == 0) ACE_THROW_RETURN (CosNaming::NamingContext::InvalidName(), CosNaming::NamingContext::_nil ()); ACE_GUARD_THROW_EX (ACE_SYNCH_RECURSIVE_MUTEX, ace_mon, this->lock_, CORBA::INTERNAL ()); ACE_CHECK_RETURN (CosNaming::NamingContext::_nil ()); // Check to make sure this object didn't have method // invoked on it. if (this->destroyed_) ACE_THROW_RETURN (CORBA::OBJECT_NOT_EXIST (), CosNaming::NamingContext::_nil ()); // Open the backing file File_Open_Lock_and_Check flck(this, name_len > 1 ? "r" : "rw" ACE_ENV_ARG_PARAMETER); ACE_CHECK_RETURN (CosNaming::NamingContext::_nil ()); // Check to make sure this object didn't have method // invoked on it. if (this->destroyed_) ACE_THROW_RETURN (CORBA::OBJECT_NOT_EXIST (), CosNaming::NamingContext::_nil ()); // 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) { // This had been a read on the file so now we are done with it flck.release(); CosNaming::NamingContext_var context = get_context (n ACE_ENV_ARG_PARAMETER); ACE_CHECK_RETURN (CosNaming::NamingContext::_nil ()); CosNaming::Name simple_name; simple_name.length (1); simple_name[0] = n[name_len - 1]; return context->bind_new_context (simple_name ACE_ENV_ARG_PARAMETER); ACE_CHECK_RETURN (CosNaming::NamingContext::_nil ()); } // If we received a simple name, we need to bind it in this context. else { // This had been a read on the file so now we are done with it flck.release(); // Stores our new Naming Context. CosNaming::NamingContext_var result = CosNaming::NamingContext::_nil (); // Create new context. result = new_context (ACE_ENV_SINGLE_ARG_PARAMETER); ACE_CHECK_RETURN (CosNaming::NamingContext::_nil ()); // Bind the new context to the name. ACE_TRY { bind_context (n, result.in () ACE_ENV_ARG_PARAMETER); ACE_TRY_CHECK; } ACE_CATCHANY { { ACE_DECLARE_NEW_CORBA_ENV; ACE_TRY_EX(DESTROY) { result->destroy (ACE_ENV_SINGLE_ARG_PARAMETER); ACE_TRY_CHECK_EX(DESTROY); } ACE_CATCHANY { // Do nothing? } ACE_ENDTRY; } // Re-raise the exception in bind_context() ACE_RE_THROW; } ACE_ENDTRY; ACE_CHECK_RETURN (CosNaming::NamingContext::_nil ()); return result._retn (); } } void TAO_Storable_Naming_Context::destroy (ACE_ENV_SINGLE_ARG_DECL) { ACE_TRACE("destroy"); ACE_GUARD_THROW_EX (ACE_SYNCH_RECURSIVE_MUTEX, ace_mon, this->lock_, CORBA::INTERNAL ()); ACE_CHECK; // Open the backing file File_Open_Lock_and_Check flck(this, "rw" ACE_ENV_ARG_PARAMETER); ACE_CHECK; // Check to make sure this object didn't have method // invoked on it. if (this->destroyed_) ACE_THROW (CORBA::OBJECT_NOT_EXIST ()); if (this->context_->current_size () != 0) ACE_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 ()); ACE_CHECK; poa->deactivate_object (id.in () ACE_ENV_ARG_PARAMETER); ACE_CHECK; this->Write(flck.peer()); } } void TAO_Storable_Naming_Context::bind (const CosNaming::Name& n, CORBA::Object_ptr obj ACE_ENV_ARG_DECL) { ACE_TRACE("TAO_Storable_Naming_Context::bind"); // Get the length of the name. CORBA::ULong name_len = n.length (); // Check for invalid name. if (name_len == 0) ACE_THROW (CosNaming::NamingContext::InvalidName()); // we didn't need a lock to check the input arg, but now we do ACE_GUARD_THROW_EX (ACE_SYNCH_RECURSIVE_MUTEX, ace_mon, this->lock_, CORBA::INTERNAL ()); ACE_CHECK; // Open the backing file File_Open_Lock_and_Check flck(this, name_len > 1 ? "r" : "rw" ACE_ENV_ARG_PARAMETER); ACE_CHECK; // Check to make sure this object didn't have method // invoked on it. if (this->destroyed_) ACE_THROW (CORBA::OBJECT_NOT_EXIST ()); // 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) { // This had been a read on the file so now we are done with it flck.release(); CosNaming::NamingContext_var context = get_context (n ACE_ENV_ARG_PARAMETER); ACE_CHECK; CosNaming::Name simple_name; simple_name.length (1); simple_name[0] = n[name_len - 1]; context->bind (simple_name, obj ACE_ENV_ARG_PARAMETER); ACE_CHECK; } // 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) ACE_THROW (CosNaming::NamingContext::AlreadyBound()); // Something went wrong with the internal structure else if (result == -1) ACE_THROW (CORBA::INTERNAL ()); this->Write(flck.peer()); } } void TAO_Storable_Naming_Context::list (CORBA::ULong how_many, CosNaming::BindingList_out &bl, CosNaming::BindingIterator_out &bi ACE_ENV_ARG_DECL) { ACE_TRACE("list"); // Allocate nil out parameters in case we won't be able to complete // the operation. bi = CosNaming::BindingIterator::_nil (); ACE_NEW_THROW_EX (bl, CosNaming::BindingList (0), CORBA::NO_MEMORY ()); ACE_CHECK; // Obtain a lock before we proceed with the operation. ACE_GUARD_THROW_EX (ACE_SYNCH_RECURSIVE_MUTEX, ace_mon, this->lock_, CORBA::INTERNAL ()); ACE_CHECK; // Open the backing file File_Open_Lock_and_Check flck(this, "r" ACE_ENV_ARG_PARAMETER); ACE_CHECK; // Check to make sure this object didn't have method // invoked on it. if (this->destroyed_) ACE_THROW (CORBA::OBJECT_NOT_EXIST ()); // We have the map in memory, let the disk go flck.release(); // Dynamically allocate iterator for traversing the underlying hash map. HASH_MAP::ITERATOR *hash_iter = 0; ACE_NEW_THROW_EX (hash_iter, HASH_MAP::ITERATOR (storable_context_->map ()), CORBA::NO_MEMORY ()); ACE_CHECK; // Store temp (hash_iter); // Silliness below is required because of broken old g++!!! E.g., // without it, we could have just said HASH_MAP::ITERATOR everywhere we use ITER_DEF. typedef ACE_Hash_Map_Manager::ITERATOR ITER_DEF; typedef ACE_Hash_Map_Manager::ENTRY ENTRY_DEF; // Typedef to the type of BindingIterator servant for ease of use. typedef TAO_Bindings_Iterator ITER_SERVANT; // A pointer to BindingIterator servant. ITER_SERVANT *bind_iter = 0; // Number of bindings that will go into the BindingList . CORBA::ULong n; // Calculate number of bindings that will go into . if (this->context_->current_size () > how_many) n = how_many; else n = ACE_static_cast (CORBA::ULong, this->context_->current_size ()); // Use the hash map iterator to populate with bindings. bl->length (n); ENTRY_DEF *hash_entry; for (CORBA::ULong i = 0; i < n; i++) { hash_iter->next (hash_entry); hash_iter->advance (); if (ITER_SERVANT::populate_binding (hash_entry, bl[i]) == 0) ACE_THROW (CORBA::NO_MEMORY()); } // Now we are done with the BindingsList, and we can follow up on // the BindingIterator business. // If we do not need to pass back BindingIterator. if (this->context_->current_size () <= how_many) return; else { // *** This is a problem. Is there an exception we can throw? *** ACE_UNUSED_ARG (bind_iter); ACE_THROW (CORBA::NO_IMPLEMENT ()); #if 0 // Create a BindingIterator for return. ACE_NEW_THROW_EX (bind_iter, ITER_SERVANT (this, hash_iter, this->poa_.in (), this->lock_), CORBA::NO_MEMORY ()); ACE_CHECK; // Release from auto pointer, and start using // reference counting to control our servant. temp.release (); PortableServer::ServantBase_var iter = bind_iter; // Increment reference count on this Naming Context, so it doesn't get // deleted before the BindingIterator servant gets deleted. interface_->_add_ref (ACE_ENV_SINGLE_ARG_PARAMETER); ACE_CHECK; // Register with the POA. char poa_id[BUFSIZ]; ACE_OS::sprintf (poa_id, "%s_%d", this->poa_id_.c_str (), this->counter_++); PortableServer::ObjectId_var id = PortableServer::string_to_ObjectId (poa_id); this->poa_->activate_object_with_id (id.in (), bind_iter ACE_ENV_ARG_PARAMETER); ACE_CHECK; bi = bind_iter->_this (ACE_ENV_SINGLE_ARG_PARAMETER); ACE_CHECK; #endif /* 0 */ } } #include "Naming_Service_Container.h" CosNaming::NamingContext_ptr TAO_Storable_Naming_Context::recreate_all( CORBA::ORB_ptr orb, PortableServer::POA_ptr poa, const char *poa_id, size_t context_size, int reentering, TAO_Naming_Service_Persistence_Factory *factory, const ACE_TCHAR *persistence_directory, int use_redundancy ACE_ENV_ARG_DECL) { ACE_TRACE("recreate_all"); ACE_UNUSED_ARG (reentering); // Whether we are redundant is global redundant_ = use_redundancy; // Save the root name for later use root_name_ = poa_id; // Create a new context. TAO_Storable_Naming_Context *new_context = 0; CosNaming::NamingContext_var result = make_new_context (orb, poa, poa_id, context_size, factory, persistence_directory, &new_context ACE_ENV_ARG_PARAMETER); ACE_CHECK_RETURN (CosNaming::NamingContext::_nil ()); // Now does this already exist on disk? ACE_TString file_name(persistence_directory); file_name += ACE_TEXT("/"); file_name += ACE_TEXT_CHAR_TO_TCHAR(poa_id); ACE_Auto_Ptr fl (factory->create_stream(ACE_TEXT_ALWAYS_CHAR(file_name.c_str()), ACE_TEXT("r"))); if (fl->exists()) { // Load the map from disk File_Open_Lock_and_Check flck(new_context, "r" ACE_ENV_ARG_PARAMETER); ACE_CHECK_RETURN (CosNaming::NamingContext::_nil ()); } else { // Since this is a new context, make and empty map in it ACE_NEW_THROW_EX (new_context->storable_context_, TAO_Storable_Bindings_Map (context_size,orb), CORBA::NO_MEMORY ()); ACE_CHECK_RETURN (CosNaming::NamingContext::_nil ()); new_context->context_ = new_context->storable_context_; File_Open_Lock_and_Check flck(new_context, "wc" ACE_ENV_ARG_PARAMETER); ACE_CHECK_RETURN (CosNaming::NamingContext::_nil ()); new_context->Write(flck.peer()); } // build the global file name file_name += ACE_TEXT("_global"); // Create the stream for the counter used to uniquely creat context names gfl_.reset(factory->create_stream(ACE_TEXT_ALWAYS_CHAR(file_name.c_str()), ACE_TEXT("crw"))); if (gfl_->open() != 0) { delete gfl_.release(); ACE_THROW_RETURN(CORBA::PERSIST_STORE(), CosNaming::NamingContext::_nil ()); } // get the counter from disk TAO_NS_Persistence_Global global; *gfl_.get() >> global; gcounter_ = global.counter(); if(redundant_) gfl_->close(); return result._retn (); } #if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) template class ACE_Unbounded_List_Iterator; template class ACE_Unbounded_List; template class ACE_NS_Node; template class ACE_Auto_Basic_Ptr; template class ACE_Hash_Map_Manager; template class ACE_Hash_Map_Manager_Ex, ACE_Equal_To, ACE_Null_Mutex>; template class ACE_Hash_Map_Entry; template class ACE_Hash_Map_Iterator_Base_Ex, ACE_Equal_To, ACE_Null_Mutex>; template class ACE_Hash_Map_Iterator; template class ACE_Hash_Map_Iterator_Ex, ACE_Equal_To, ACE_Null_Mutex>; template class ACE_Hash_Map_Reverse_Iterator; template class ACE_Hash_Map_Reverse_Iterator_Ex, ACE_Equal_To, ACE_Null_Mutex>; template class ACE_Auto_Basic_Ptr, ACE_Equal_To, ACE_Null_Mutex > >; template class TAO_Bindings_Iterator, ACE_Equal_To, ACE_Null_Mutex>, ACE_Hash_Map_Entry >; template class ACE_Auto_Basic_Ptr, ACE_Equal_To, ACE_Null_Mutex>, ACE_Hash_Map_Entry > >; #elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) #pragma instantiate ACE_Hash_Map_Manager #pragma instantiate ACE_Hash_Map_Manager_Ex, ACE_Equal_To, ACE_Null_Mutex> #pragma instantiate ACE_Hash_Map_Entry #pragma instantiate ACE_Hash_Map_Iterator_Base_Ex, ACE_Equal_To, ACE_Null_Mutex> #pragma instantiate ACE_Hash_Map_Iterator #pragma instantiate ACE_Hash_Map_Iterator_Ex, ACE_Equal_To, ACE_Null_Mutex> #pragma instantiate ACE_Hash_Map_Reverse_Iterator #pragma instantiate ACE_Hash_Map_Reverse_Iterator_Ex, ACE_Equal_To, ACE_Null_Mutex> #pragma instantiate ACE_Auto_Basic_Ptr, ACE_Equal_To, ACE_Null_Mutex> > #pragma instantiate TAO_Bindings_Iterator, ACE_Equal_To, ACE_Null_Mutex>, ACE_Hash_Map_Entry > #pragma instantiate ACE_Auto_Basic_Ptr, ACE_Equal_To, ACE_Null_Mutex>, ACE_Hash_Map_Entry > > #pragma instantiate ACE_Unbounded_List_Iterator #pragma instantiate ACE_Unbounded_List #pragma instantiate ACE_NS_Node #pragma instantiate ACE_Auto_Basic_Ptr #endif