summaryrefslogtreecommitdiff
path: root/TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context.cpp')
-rw-r--r--TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context.cpp1584
1 files changed, 1584 insertions, 0 deletions
diff --git a/TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context.cpp b/TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context.cpp
new file mode 100644
index 00000000000..cdcfa73cb3d
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context.cpp
@@ -0,0 +1,1584 @@
+#include "orbsvcs/Naming/Storable_Naming_Context.h"
+#include "orbsvcs/Naming/Bindings_Iterator_T.h"
+
+#include "tao/debug.h"
+
+// 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<ACE_Hash_Map_Iterator_Ex<TAO_...> > 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"
+
+ACE_RCSID (Naming,
+ Storable_Naming_Context,
+ "$Id$")
+
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+const char * TAO_Storable_Naming_Context::root_name_;
+ACE_UINT32 TAO_Storable_Naming_Context::gcounter_;
+ACE_Auto_Ptr<TAO_Storable_Base> TAO_Storable_Naming_Context::gfl_;
+int TAO_Storable_Naming_Context::redundant_;
+
+TAO_Storable_IntId::TAO_Storable_IntId (void)
+ : ref_ (CORBA::string_dup ("")),
+ 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_ (CORBA::string_dup ("")),
+ kind_ (CORBA::string_dup (""))
+{
+}
+
+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 (static_cast<unsigned int> (storable_context_->current_size()));
+ header.destroyed (destroyed_);
+
+ wrtr << header;
+
+ if (0u == header.size ())
+ return;
+
+ ACE_Hash_Map_Iterator<TAO_Storable_ExtId,TAO_Storable_IntId,
+ ACE_Null_Mutex> it = storable_context_->map().begin();
+ ACE_Hash_Map_Iterator<TAO_Storable_ExtId,TAO_Storable_IntId,
+ ACE_Null_Mutex> itend = storable_context_->map().end();
+
+ ACE_Hash_Map_Entry<TAO_Storable_ExtId,TAO_Storable_IntId> ent = *it;
+
+ while (!(it == itend))
+ {
+ TAO_NS_Persistence_Record record;
+
+ ACE_CString name;
+ CosNaming::BindingType bt = (*it).int_id_.type_;
+ if (bt == CosNaming::ncontext)
+ {
+ CORBA::Object_var
+ obj = orb_->string_to_object ((*it).int_id_.ref_.in ());
+ if (obj->_is_collocated ())
+ {
+ // This is a local (i.e. non federated context) we therefore
+ // store only the ObjectID (persistence filename) for the object.
+
+ // The driving force behind storing ObjectIDs rather than IORs for
+ // local contexts is to provide for a redundant naming service.
+ // That is, a naming service that runs simultaneously on multiple
+ // machines sharing a file system. It allows multiple redundant
+ // copies to be started and stopped independently.
+ // The original target platform was Tru64 Clusters where there was
+ // a cluster address. In that scenario, clients may get different
+ // servers on each request, hence the requirement to keep
+ // synchronized to the disk. It also works on non-cluster system
+ // where the client picks one of the redundant servers and uses it,
+ // while other systems can pick different servers. (However in this
+ // scenario, if a server fails and a client must pick a new server,
+ // that client may not use any saved context IORs, instead starting
+ // from the root to resolve names. So this latter mode is not quite
+ // transparent to clients.) [Rich Seibel (seibel_r) of ociweb.com]
+
+ 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); // The local ObjectID (persistance filename)
+ record.type (TAO_NS_Persistence_Record::LOCAL_NCONTEXT);
+ }
+ else
+ {
+ // Since this is a foreign (federated) context, we can not store
+ // the objectID (because it isn't in our storage), if we did, when
+ // we restore, we would end up either not finding a permanent
+ // record (and thus ending up incorrectly assuming the context was
+ // destroyed) or loading another context altogether (just because
+ // the contexts shares its objectID filename which is very likely).
+ // [Simon Massey (sma) of prismtech.com]
+
+ name.set ((*it).int_id_.ref_.in ()); // The federated context IOR
+ record.type (TAO_NS_Persistence_Record::REMOTE_NCONTEXT);
+ }
+ }
+ else // if (bt == CosNaming::nobject) // shouldn't be any other, can there?
+ {
+ name.set ((*it).int_id_.ref_.in ()); // The non-context object IOR
+ record.type (TAO_NS_Persistence_Record::OBJREF);
+ }
+ record.ref(name);
+
+ 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);
+
+ 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;
+ if (!flck->peer ().good ())
+ {
+ flck->peer ().clear ();
+ ACE_THROW_RETURN (CORBA::INTERNAL (), -1);
+ }
+
+ // reset the destroyed flag
+ this->destroyed_ = header.destroyed();
+
+ // read in the data for the map
+ for (unsigned int i= 0u; i<header.size(); ++i)
+ {
+ flck->peer() >> record;
+ if (!flck->peer ().good ())
+ {
+ flck->peer ().clear ();
+ ACE_THROW_RETURN (CORBA::INTERNAL (), -1);
+ }
+
+ if (TAO_NS_Persistence_Record::LOCAL_NCONTEXT == record.type ())
+ {
+ 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 (),
+ ((TAO_NS_Persistence_Record::REMOTE_NCONTEXT == record.type ())
+ ? CosNaming::ncontext // REMOTE_NCONTEXT
+ : CosNaming::nobject )); // OBJREF
+ }
+ }
+ 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; i<ACE_OS::strlen(mode); i++ )
+ {
+ switch (mode[i])
+ {
+ case 'r': rwflags_ |= mode_read;
+ break;
+ case 'w': rwflags_ |= mode_write;
+ break;
+ case 'c': rwflags_ |= mode_create;
+ break;
+ default: rwflags_ = -1;
+ }
+ }
+ if( rwflags_ <= 0 )
+ {
+ errno = EINVAL;
+ ACE_THROW(CORBA::PERSIST_STORE());
+ }
+
+ // build the file name
+ ACE_CString file_name(context->persistence_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<TAO_Storable_Base>
+ fl (
+ this->factory_->create_stream(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 <context_impl> into the auto pointer temporarily, in case next
+ // allocation fails.
+ ACE_Auto_Basic_Ptr<TAO_Storable_Naming_Context> 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 <implementation> know about it's <interface>.
+ 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 <destroy> 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;
+ if (!gfl_.get ()->good () &&
+ gfl_.get ()->rdstate () != TAO_Storable_Base::eofbit)
+ {
+ gfl_.get ()->clear ();
+ ACE_THROW_RETURN (CORBA::INTERNAL (), 0);
+ }
+ 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 <destroy> 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 <destroy> 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 <destroy> 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 <destroy> 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 <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.
+ 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 <destroy> 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 <destroy> 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 <destroy> 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.
+
+ // 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 <destroy> 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 <destroy> 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 <destroy> 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 <hash_iter temporarily in auto pointer, in case we'll have
+ // some failures and throw an exception.
+ ACE_Auto_Basic_Ptr<HASH_MAP::ITERATOR> 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<TAO_Storable_ExtId,
+ TAO_Storable_IntId,
+ ACE_Null_Mutex>::ITERATOR ITER_DEF;
+ typedef ACE_Hash_Map_Manager<TAO_Storable_ExtId,
+ TAO_Storable_IntId,
+ ACE_Null_Mutex>::ENTRY ENTRY_DEF;
+
+ // Typedef to the type of BindingIterator servant for ease of use.
+ typedef TAO_Bindings_Iterator<ITER_DEF, ENTRY_DEF> ITER_SERVANT;
+
+ // A pointer to BindingIterator servant.
+ ITER_SERVANT *bind_iter = 0;
+
+ // Number of bindings that will go into the BindingList <bl>.
+ CORBA::ULong n;
+
+ // Calculate number of bindings that will go into <bl>.
+ if (this->context_->current_size () > how_many)
+ n = how_many;
+ else
+ n = static_cast<CORBA::ULong> (this->context_->current_size ());
+
+ // Use the hash map iterator to populate <bl> with bindings.
+ bl->length (n);
+
+ ENTRY_DEF *hash_entry = 0;
+
+ 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 <hash_iter> 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 */
+ }
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+#include "orbsvcs/Naming/Naming_Service_Container.h"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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<TAO_Storable_Base> 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;
+ if (!gfl_.get ()->good () &&
+ gfl_.get ()->rdstate () != TAO_Storable_Base::eofbit)
+ {
+ gfl_.get ()->clear ();
+ ACE_THROW_RETURN (CORBA::INTERNAL (), 0);
+ }
+ gcounter_ = global.counter();
+ if(redundant_) gfl_->close();
+
+ return result._retn ();
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL