Storable_Naming_Context.cpp

Go to the documentation of this file.
00001 #include "orbsvcs/Naming/Storable_Naming_Context.h"
00002 #include "orbsvcs/Naming/Bindings_Iterator_T.h"
00003 
00004 #include "tao/debug.h"
00005 
00006 // The following #pragma is needed to disable a warning that occurs
00007 // in MSVC 6 due to the overly long debugging symbols generated for
00008 // the ACE_Auto_Basic_Ptr<ACE_Hash_Map_Iterator_Ex<TAO_...> > template
00009 // instance used by some of the methods in this file.
00010 #ifdef _MSC_VER
00011 #  pragma warning(disable: 4786)  /* identifier was truncated to '255'
00012                                      characters in the browser
00013                                      information */
00014 #endif  /* _MSC_VER */
00015 
00016 #include "ace/Auto_Ptr.h"
00017 #include "ace/OS_NS_stdio.h"
00018 
00019 ACE_RCSID (Naming,
00020            Storable_Naming_Context,
00021            "$Id: Storable_Naming_Context.cpp 77276 2007-02-21 08:26:36Z johnnyw $")
00022 
00023 
00024 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00025 
00026 const char * TAO_Storable_Naming_Context::root_name_;
00027 ACE_UINT32 TAO_Storable_Naming_Context::gcounter_;
00028 ACE_Auto_Ptr<TAO_Storable_Base> TAO_Storable_Naming_Context::gfl_;
00029 int TAO_Storable_Naming_Context::redundant_;
00030 
00031 TAO_Storable_IntId::TAO_Storable_IntId (void)
00032   : ref_ (CORBA::string_dup ("")),
00033     type_ (CosNaming::nobject)
00034 {
00035 }
00036 
00037 TAO_Storable_IntId::TAO_Storable_IntId (const char * ior,
00038                                             CosNaming::BindingType type)
00039   : ref_ (ior),
00040     type_ (type)
00041 {
00042 }
00043 
00044 TAO_Storable_IntId::TAO_Storable_IntId (const TAO_Storable_IntId &rhs)
00045 {
00046   ref_ = rhs.ref_;
00047   type_ = rhs.type_;
00048 }
00049 
00050 TAO_Storable_IntId::~TAO_Storable_IntId (void)
00051 {
00052 }
00053 
00054 void
00055 TAO_Storable_IntId::operator= (const TAO_Storable_IntId &rhs)
00056 {
00057   // check for self assignment.
00058   if (&rhs == this)
00059     return;
00060 
00061   type_ = rhs.type_;
00062   ref_ = rhs.ref_;
00063 }
00064 
00065 TAO_Storable_ExtId::TAO_Storable_ExtId (void)
00066   : id_ (CORBA::string_dup ("")),
00067     kind_ (CORBA::string_dup (""))
00068 {
00069 }
00070 
00071 TAO_Storable_ExtId::TAO_Storable_ExtId (const char *id, const char *kind)
00072   : id_ (id)
00073   , kind_ (kind)
00074 {
00075 }
00076 
00077 TAO_Storable_ExtId::TAO_Storable_ExtId (const TAO_Storable_ExtId &rhs)
00078 {
00079   id_ = rhs.id_;
00080   kind_ = rhs.kind_;
00081 }
00082 
00083 TAO_Storable_ExtId::~TAO_Storable_ExtId (void)
00084 {
00085 }
00086 
00087 void
00088 TAO_Storable_ExtId::operator= (const TAO_Storable_ExtId &rhs)
00089 {
00090   // Check for self assignment.
00091   if (&rhs == this)
00092     return;
00093 
00094   id_ = rhs.id_;
00095   kind_ = rhs.kind_;
00096 }
00097 
00098 bool
00099 TAO_Storable_ExtId::operator== (const TAO_Storable_ExtId &rhs) const
00100 {
00101   return (ACE_OS::strcmp (id_.in(), rhs.id_.in()) == 0)
00102     && (ACE_OS::strcmp (kind_.in(), rhs.kind_.in()) == 0);
00103 }
00104 
00105 bool
00106 TAO_Storable_ExtId::operator!= (const TAO_Storable_ExtId &rhs) const
00107 {
00108   return (ACE_OS::strcmp (id_.in(), rhs.id_.in()) != 0)
00109     || (ACE_OS::strcmp (kind_.in(), rhs.kind_.in()) != 0);
00110 }
00111 
00112 u_long
00113 TAO_Storable_ExtId::hash (void) const
00114 {
00115   // @CJC I wager this could be optimized a bit better, but I'm not
00116   // sure how much it's called.  At the very least, we could allocate
00117   // just one ACE_CString, and copy id_ and kind_ into that, rather than
00118   // taking a double-hit on allocations.
00119   ACE_CString temp (id_.in());
00120   temp += kind_.in();
00121 
00122   return temp.hash ();
00123 }
00124 
00125 const char *
00126 TAO_Storable_ExtId::id (void)
00127 {
00128   return id_.in();
00129 }
00130 
00131 const char *
00132 TAO_Storable_ExtId::kind (void)
00133 {
00134   return kind_.in();
00135 }
00136 
00137 int
00138 TAO_Storable_Bindings_Map::unbind (const char *id, const char *kind)
00139 {
00140   ACE_TRACE("unbind");
00141   TAO_Storable_ExtId name (id, kind);
00142   return this->map_.unbind (name);
00143 }
00144 
00145 int
00146 TAO_Storable_Bindings_Map::bind (const char *id,
00147                                  const char *kind,
00148                                  CORBA::Object_ptr obj,
00149                                  CosNaming::BindingType type)
00150 {
00151   ACE_TRACE("bind");
00152   return this->shared_bind (id, kind, obj, type, 0);
00153 }
00154 
00155 int
00156 TAO_Storable_Bindings_Map::rebind (const char *id,
00157                                    const char *kind,
00158                                    CORBA::Object_ptr obj,
00159                                    CosNaming::BindingType type)
00160 {
00161   ACE_TRACE("rebind");
00162   return this->shared_bind (id, kind, obj, type, 1);
00163 }
00164 
00165 int
00166 TAO_Storable_Bindings_Map::find (const char *id,
00167                                  const char *kind,
00168                                  CORBA::Object_ptr & obj,
00169                                  CosNaming::BindingType &type)
00170 {
00171   ACE_TRACE("find");
00172   TAO_Storable_ExtId name (id, kind);
00173   TAO_Storable_IntId entry;
00174 
00175   if (this->map_.find (name, entry) != 0)
00176     {
00177       return -1;
00178     }
00179   else
00180     {
00181       obj = orb_->string_to_object (entry.ref_.in());
00182       type = entry.type_;
00183 
00184       return 0;
00185     }
00186 }
00187 
00188 TAO_Storable_Bindings_Map::TAO_Storable_Bindings_Map (size_t hash_table_size,
00189                                                       CORBA::ORB_ptr orb)
00190   : map_ (hash_table_size),
00191     orb_(CORBA::ORB::_duplicate (orb))
00192 {
00193   ACE_TRACE("TAO_Storable_Bindings_Map");
00194 }
00195 
00196 TAO_Storable_Bindings_Map::~TAO_Storable_Bindings_Map (void)
00197 {
00198   ACE_TRACE("~TAO_Storable_Bindings_Map");
00199 }
00200 
00201 TAO_Storable_Bindings_Map::HASH_MAP &
00202 TAO_Storable_Bindings_Map::map (void)
00203 {
00204   ACE_TRACE("map");
00205   return map_;
00206 }
00207 
00208 size_t
00209 TAO_Storable_Bindings_Map::current_size (void)
00210 {
00211   ACE_TRACE("current_size");
00212   return map_.current_size ();
00213 }
00214 
00215 size_t
00216 TAO_Storable_Bindings_Map::total_size (void)
00217 {
00218   ACE_TRACE("total_size");
00219   return map_.total_size ();
00220 }
00221 
00222 int
00223 TAO_Storable_Bindings_Map::shared_bind (const char * id,
00224                                         const char * kind,
00225                                         CORBA::Object_ptr obj,
00226                                         CosNaming::BindingType type,
00227                                         int rebind)
00228 {
00229   ACE_TRACE("shared_bind");
00230   TAO_Storable_ExtId new_name (id, kind);
00231   CORBA::String_var ior = orb_->object_to_string(obj);
00232   TAO_Storable_IntId new_entry (ior.in(), type);
00233   TAO_Storable_IntId old_entry;
00234 
00235   if (rebind == 0)
00236     {
00237       // Do a normal bind.
00238       return this->map_.bind (new_name, new_entry);
00239     }
00240   else
00241     // Rebind.
00242     {
00243       // Check that types of old and new entries match.
00244       if (this->map_.find (new_name,
00245                            old_entry) == 0
00246           && type != old_entry.type_)
00247         return -2;
00248 
00249       else
00250         return this->map_.rebind (new_name, new_entry);
00251     }
00252 }
00253 
00254 void TAO_Storable_Naming_Context::Write(TAO_Storable_Base& wrtr)
00255 {
00256   ACE_TRACE("Write");
00257   TAO_NS_Persistence_Header header;
00258 
00259   header.size (static_cast<unsigned int> (storable_context_->current_size()));
00260   header.destroyed (destroyed_);
00261 
00262   wrtr << header;
00263 
00264   if (0u == header.size ())
00265     return;
00266 
00267   ACE_Hash_Map_Iterator<TAO_Storable_ExtId,TAO_Storable_IntId,
00268                         ACE_Null_Mutex> it = storable_context_->map().begin();
00269   ACE_Hash_Map_Iterator<TAO_Storable_ExtId,TAO_Storable_IntId,
00270                         ACE_Null_Mutex> itend = storable_context_->map().end();
00271 
00272   ACE_Hash_Map_Entry<TAO_Storable_ExtId,TAO_Storable_IntId> ent = *it;
00273 
00274   while (!(it == itend))
00275   {
00276     TAO_NS_Persistence_Record record;
00277 
00278     ACE_CString name;
00279     CosNaming::BindingType bt = (*it).int_id_.type_;
00280     if (bt ==  CosNaming::ncontext)
00281       {
00282         CORBA::Object_var
00283           obj = orb_->string_to_object ((*it).int_id_.ref_.in ());
00284         if (obj->_is_collocated ())
00285           {
00286             // This is a local (i.e. non federated context) we therefore
00287             // store only the ObjectID (persistence filename) for the object.
00288 
00289             // The driving force behind storing ObjectIDs rather than IORs for
00290             // local contexts is to provide for a redundant naming service.
00291             // That is, a naming service that runs simultaneously on multiple
00292             // machines sharing a file system. It allows multiple redundant
00293             // copies to be started and stopped independently.
00294             // The original target platform was Tru64 Clusters where there was
00295             // a cluster address. In that scenario, clients may get different
00296             // servers on each request, hence the requirement to keep
00297             // synchronized to the disk. It also works on non-cluster system
00298             // where the client picks one of the redundant servers and uses it,
00299             // while other systems can pick different servers. (However in this
00300             // scenario, if a server fails and a client must pick a new server,
00301             // that client may not use any saved context IORs, instead starting
00302             // from the root to resolve names. So this latter mode is not quite
00303             // transparent to clients.) [Rich Seibel (seibel_r) of ociweb.com]
00304 
00305             PortableServer::ObjectId_var
00306               oid = poa_->reference_to_id (obj.in ());
00307             CORBA::String_var
00308               nm = PortableServer::ObjectId_to_string (oid.in ());
00309             const char
00310               *newname = nm.in ();
00311             name.set (newname); // The local ObjectID (persistance filename)
00312             record.type (TAO_NS_Persistence_Record::LOCAL_NCONTEXT);
00313           }
00314         else
00315           {
00316             // Since this is a foreign (federated) context, we can not store
00317             // the objectID (because it isn't in our storage), if we did, when
00318             // we restore, we would end up either not finding a permanent
00319             // record (and thus ending up incorrectly assuming the context was
00320             // destroyed) or loading another context altogether (just because
00321             // the contexts shares its objectID filename which is very likely).
00322             // [Simon Massey  (sma) of prismtech.com]
00323 
00324             name.set ((*it).int_id_.ref_.in ()); // The federated context IOR
00325             record.type (TAO_NS_Persistence_Record::REMOTE_NCONTEXT);
00326           }
00327       }
00328     else // if (bt == CosNaming::nobject) // shouldn't be any other, can there?
00329       {
00330         name.set ((*it).int_id_.ref_.in ()); // The non-context object IOR
00331         record.type (TAO_NS_Persistence_Record::OBJREF);
00332       }
00333     record.ref(name);
00334 
00335     const char *myid = (*it).ext_id_.id();
00336     ACE_CString id(myid);
00337     record.id(id);
00338 
00339     const char *mykind = (*it).ext_id_.kind();
00340     ACE_CString kind(mykind);
00341     record.kind(kind);
00342 
00343     wrtr << record;
00344     it.advance();
00345   }
00346 }
00347 
00348 // Helper function to load a new context into the binding_map
00349 int
00350 TAO_Storable_Naming_Context::load_map(File_Open_Lock_and_Check *flck)
00351 {
00352   ACE_TRACE("load_map");
00353   // assume file already open for reading
00354   TAO_Storable_Bindings_Map *bindings_map;
00355 
00356   // create the new bindings map
00357   ACE_NEW_THROW_EX (bindings_map,
00358                     TAO_Storable_Bindings_Map (hash_table_size_,orb_.in()),
00359                     CORBA::NO_MEMORY ());
00360 
00361   // get the data for this bindings map from the file
00362 
00363   TAO_NS_Persistence_Header header;
00364   TAO_NS_Persistence_Record record;
00365 
00366   // we are only using the size from this header
00367   flck->peer() >> header;
00368   if (!flck->peer ().good ())
00369     {
00370       flck->peer ().clear ();
00371       throw CORBA::INTERNAL ();
00372     }
00373 
00374   // reset the destroyed flag
00375   this->destroyed_ = header.destroyed();
00376 
00377   // read in the data for the map
00378   for (unsigned int i= 0u; i<header.size(); ++i)
00379     {
00380       flck->peer() >> record;
00381       if (!flck->peer ().good ())
00382         {
00383           flck->peer ().clear ();
00384           throw CORBA::INTERNAL ();
00385         }
00386 
00387       if (TAO_NS_Persistence_Record::LOCAL_NCONTEXT == record.type ())
00388         {
00389           PortableServer::ObjectId_var
00390             id = PortableServer::string_to_ObjectId (record.ref ().c_str ());
00391           const char
00392             *intf = interface_->_interface_repository_id ();
00393           CORBA::Object_var
00394             objref = poa_->create_reference_with_id (id.in (), intf);
00395           bindings_map->bind ( record.id ().c_str (),
00396                                record.kind ().c_str (),
00397                                objref.in (),
00398                                CosNaming::ncontext );
00399         }
00400       else
00401         {
00402           CORBA::Object_var
00403             objref = orb_->string_to_object (record.ref ().c_str ());
00404           bindings_map->bind ( record.id ().c_str (),
00405                                record.kind ().c_str (),
00406                                objref.in (),
00407                                ((TAO_NS_Persistence_Record::REMOTE_NCONTEXT == record.type ())
00408                                 ? CosNaming::ncontext    // REMOTE_NCONTEXT
00409                                 : CosNaming::nobject )); // OBJREF
00410         }
00411     }
00412   storable_context_ = bindings_map;
00413   context_ = storable_context_;
00414   return 0;
00415 }
00416 
00417 TAO_Storable_Naming_Context::
00418 File_Open_Lock_and_Check::File_Open_Lock_and_Check(
00419                                  TAO_Storable_Naming_Context * context,
00420                                  const char * mode)
00421 :closed_(1),
00422  context_(context)
00423 {
00424   ACE_TRACE("File_Open_Lock_and_Check");
00425   // We only accept a subset of mode argument, check it
00426   rwflags_ = 0;
00427   for( unsigned int i = 0; i<ACE_OS::strlen(mode); i++ )
00428   {
00429     switch (mode[i])
00430     {
00431       case 'r': rwflags_ |= mode_read;
00432                 break;
00433       case 'w': rwflags_ |= mode_write;
00434                 break;
00435       case 'c': rwflags_ |= mode_create;
00436                 break;
00437       default: rwflags_ = -1;
00438     }
00439   }
00440   if( rwflags_ <= 0 )
00441   {
00442     errno = EINVAL;
00443     throw CORBA::PERSIST_STORE();
00444   }
00445 
00446   // build the file name
00447   ACE_CString file_name(context->persistence_directory_);
00448   file_name += "/";
00449   file_name += context->name_;
00450 
00451   // Create the stream
00452   fl_ = context->factory_->create_stream(file_name, ACE_TEXT_CHAR_TO_TCHAR(mode));
00453   if (TAO_Storable_Naming_Context::redundant_)
00454   {
00455     if (fl_->open() != 0)
00456       {
00457         delete fl_;
00458         throw CORBA::PERSIST_STORE();
00459       }
00460 
00461     // acquire a lock on it
00462     if (fl_ -> flock(0, 0, 0) != 0)
00463       {
00464          fl_->close();
00465          delete fl_;
00466          throw CORBA::INTERNAL();
00467       }
00468 
00469     // now that the file is successfully opened and locked it must be
00470     // unlocked/closed before we leave this class
00471     closed_ = 0;
00472 
00473     if ( ! (rwflags_ & mode_create) )
00474     {
00475       // Check if our copy is up to date
00476       time_t new_last_changed = fl_->last_changed();
00477       if( new_last_changed > context->last_changed_ )
00478       {
00479          context->last_changed_ = new_last_changed;
00480          // Throw our map away
00481          delete context->storable_context_;
00482          // and build a new one from disk
00483          context->load_map(this);
00484        }
00485     }
00486   }
00487   else if ( ! context->storable_context_ || (rwflags_ & mode_write) )
00488   {
00489     if (fl_->open() != 0)
00490       {
00491         delete fl_;
00492         throw CORBA::PERSIST_STORE();
00493       }
00494 
00495     // now that the file is successfully opened
00496     // unlocked/closed before we leave this class
00497     closed_ = 0;
00498 
00499     if(!context->storable_context_)
00500     {
00501       // Load the map from disk
00502       context->load_map(this);
00503     }
00504   }
00505   else
00506     {
00507       // Need to insure that fl_ gets deleted
00508       delete fl_;
00509     }
00510 }
00511 
00512 void
00513 TAO_Storable_Naming_Context::
00514 File_Open_Lock_and_Check::release(void)
00515 {
00516   ACE_TRACE("release");
00517   if ( ! closed_ )
00518   {
00519     // If we updated the disk, save the time stamp
00520     if(TAO_Storable_Naming_Context::redundant_)
00521     {
00522       if( rwflags_ & mode_write )
00523         context_->last_changed_ = fl_->last_changed();
00524       fl_->funlock(0, 0, 0);
00525     }
00526     fl_->close();
00527     delete fl_;
00528     closed_ = 1;
00529   }
00530 }
00531 
00532 TAO_Storable_Naming_Context::
00533 File_Open_Lock_and_Check::~File_Open_Lock_and_Check(void)
00534 {
00535   ACE_TRACE("~File_Open_Lock_and_Check");
00536   this->release();
00537 }
00538 
00539 TAO_Storable_Base &
00540 TAO_Storable_Naming_Context::File_Open_Lock_and_Check::peer(void)
00541 {
00542   ACE_TRACE("peer");
00543   return *fl_;
00544 }
00545 
00546 TAO_Storable_Naming_Context::TAO_Storable_Naming_Context (
00547                                CORBA::ORB_ptr orb,
00548                                PortableServer::POA_ptr poa,
00549                                const char *poa_id,
00550                                TAO_Naming_Service_Persistence_Factory *factory,
00551                                const ACE_TCHAR *persistence_directory,
00552                                size_t hash_table_size)
00553   : TAO_Hash_Naming_Context (poa,
00554                              poa_id),
00555     counter_ (0),
00556     storable_context_ (0),
00557     orb_(CORBA::ORB::_duplicate (orb)),
00558     name_ (poa_id),
00559     poa_ (PortableServer::POA::_duplicate (poa)),
00560     factory_(factory),
00561     persistence_directory_ (ACE_TEXT_ALWAYS_CHAR(persistence_directory)),
00562     hash_table_size_(hash_table_size),
00563     last_changed_(0)
00564 {
00565   ACE_TRACE("TAO_Storable_Naming_Context");
00566 }
00567 
00568 TAO_Storable_Naming_Context::~TAO_Storable_Naming_Context (void)
00569 {
00570   ACE_TRACE("~TAO_Storable_Naming_Context");
00571 
00572   // If we're in the DTOR as a result of the destroy() operation,
00573   // then we go ahead and delete the file.  Otherwise, we leave the
00574   // file around because they need to be there for persistence.
00575   if (this->destroyed_)
00576     {
00577       // Make sure we delete the associated stream
00578       ACE_CString file_name (this->persistence_directory_);
00579       file_name += "/";
00580       file_name += this->name_;
00581 
00582       // Now delete the file
00583       ACE_Auto_Ptr<TAO_Storable_Base>
00584         fl (
00585           this->factory_->create_stream(file_name.c_str(),
00586                                         ACE_TEXT("r"))
00587           );
00588       if (fl.get())
00589         {
00590           if (TAO_debug_level > 5)
00591             ACE_DEBUG ((LM_DEBUG, "(%P|%t) NameService: removing file %s\n",
00592                         file_name.fast_rep()));
00593           fl->remove ();
00594         }
00595     }
00596 }
00597 
00598 CosNaming::NamingContext_ptr
00599 TAO_Storable_Naming_Context::make_new_context (
00600                               CORBA::ORB_ptr orb,
00601                               PortableServer::POA_ptr poa,
00602                               const char *poa_id,
00603                               size_t context_size,
00604                               TAO_Naming_Service_Persistence_Factory *factory,
00605                               const ACE_TCHAR *persistence_directory,
00606                               TAO_Storable_Naming_Context **new_context)
00607 {
00608   ACE_TRACE("make_new_context");
00609   // Store the stub we will return here.
00610   CosNaming::NamingContext_var result;
00611 
00612   // Put together a servant for the new Naming Context.
00613 
00614   TAO_Storable_Naming_Context *context_impl = 0;
00615   ACE_NEW_THROW_EX (context_impl,
00616                     TAO_Storable_Naming_Context (orb,
00617                                                  poa,
00618                                                  poa_id,
00619                                                  factory,
00620                                                  persistence_directory,
00621                                                  context_size),
00622                                                  CORBA::NO_MEMORY ());
00623 
00624   // Put <context_impl> into the auto pointer temporarily, in case next
00625   // allocation fails.
00626   ACE_Auto_Basic_Ptr<TAO_Storable_Naming_Context> temp (context_impl);
00627 
00628   TAO_Naming_Context *context = 0;
00629   ACE_NEW_THROW_EX (context,
00630                     TAO_Naming_Context (context_impl),
00631                     CORBA::NO_MEMORY ());
00632 
00633   // Let <implementation> know about it's <interface>.
00634   context_impl->interface (context);
00635 
00636   // Release auto pointer, and start using reference counting to
00637   // control our servant.
00638   temp.release ();
00639   PortableServer::ServantBase_var s = context;
00640 
00641   // Register the new context with the POA.
00642   PortableServer::ObjectId_var id =
00643     PortableServer::string_to_ObjectId (poa_id);
00644 
00645   // If we try to register a naming context that is already registered,
00646   // the following activation causes a POA::ObjectAlreadyActive exception be
00647   // thrown which is transmitted as a CORBA::UNKNOWN on the wire. To rectify
00648   // this problem, we explicitly throw the correct INS exception in
00649   // this situation.
00650   try
00651     {
00652       poa->activate_object_with_id (id.in (), context);
00653     }
00654   catch (const PortableServer::POA::ObjectAlreadyActive&)
00655     {
00656       throw CosNaming::NamingContext::AlreadyBound();
00657     }
00658 
00659 
00660   result = context->_this ();
00661 
00662   // return the address of the new context object so that caller can finish
00663   *new_context = context_impl;
00664 
00665   return result._retn ();
00666 }
00667 
00668 CosNaming::NamingContext_ptr
00669 TAO_Storable_Naming_Context::new_context (void)
00670 {
00671   ACE_TRACE("new_context");
00672   ACE_GUARD_THROW_EX (ACE_SYNCH_RECURSIVE_MUTEX,
00673                       ace_mon,
00674                       this->lock_,
00675                       CORBA::INTERNAL ());
00676 
00677   {
00678     // Open the backing file
00679     File_Open_Lock_and_Check flck(this, "r");
00680 
00681     // Check to make sure this object didn't have <destroy> method
00682     // invoked on it.
00683     if (this->destroyed_)
00684       throw CORBA::OBJECT_NOT_EXIST ();
00685   }
00686 
00687   TAO_NS_Persistence_Global global;
00688 
00689   // Generate a POA id for the new context.
00690   if(redundant_)
00691   {
00692     // acquire a lock on the file that holds our counter
00693     if (gfl_->open() != 0)
00694       {
00695         delete gfl_.release();
00696         throw CORBA::PERSIST_STORE();
00697       }
00698     if (gfl_ -> flock(0, 0, 0) != 0)
00699          throw CORBA::INTERNAL();
00700     // get the counter from disk
00701     *gfl_.get() >> global;
00702     if (!gfl_.get ()->good () &&
00703         gfl_.get ()->rdstate () != TAO_Storable_Base::eofbit)
00704       {
00705         gfl_.get ()->clear ();
00706         throw CORBA::INTERNAL ();
00707       }
00708     gcounter_ = global.counter();
00709     // use it to generate a new name
00710   }
00711   char poa_id[BUFSIZ];
00712   ACE_OS::sprintf (poa_id,
00713                    "%s_%d",
00714                    root_name_,
00715                    gcounter_++);
00716   // then save it back on disk
00717   global.counter(gcounter_);
00718   *gfl_.get() << global;
00719   if(redundant_)
00720   {
00721     // and release our lock
00722     if (gfl_ -> flock(0, 0, 0) != 0)
00723          throw CORBA::INTERNAL();
00724     gfl_->close();
00725   }
00726 
00727   // Create a new context.
00728   TAO_Storable_Naming_Context *new_context = 0;
00729   CosNaming::NamingContext_var result =
00730     make_new_context (this->orb_.in (),
00731                       this->poa_.in (),
00732                       poa_id,
00733                       this->storable_context_->total_size (),
00734                       this->factory_,
00735                       ACE_TEXT_CHAR_TO_TCHAR (this->persistence_directory_.c_str ()),
00736                       &new_context);
00737 
00738   // Since this is a new context, make an empty map in it
00739   ACE_NEW_THROW_EX (new_context->storable_context_,
00740                     TAO_Storable_Bindings_Map (hash_table_size_,orb_.in ()),
00741                     CORBA::NO_MEMORY ());
00742   new_context->context_ = new_context->storable_context_;
00743 
00744   File_Open_Lock_and_Check flck(new_context, "wc");
00745   new_context->Write(flck.peer());
00746 
00747   return result._retn ();
00748 }
00749 
00750 void
00751 TAO_Storable_Naming_Context::rebind (const CosNaming::Name& n,
00752                                      CORBA::Object_ptr obj)
00753 {
00754   ACE_TRACE("rebind");
00755   // Get the length of the name.
00756   CORBA::ULong name_len = n.length ();
00757 
00758   // Check for invalid name.
00759   if (name_len == 0)
00760     throw CosNaming::NamingContext::InvalidName();
00761 
00762   // we didn't need a lock to check the input arg, but now we do
00763   ACE_GUARD_THROW_EX (ACE_SYNCH_RECURSIVE_MUTEX, ace_mon,
00764                       this->lock_,
00765                       CORBA::INTERNAL ());
00766 
00767   // Open the backing file
00768   File_Open_Lock_and_Check flck(this, name_len > 1 ? "r" : "rw");
00769 
00770   // Check to make sure this object didn't have <destroy> method
00771   // invoked on it.
00772   if (this->destroyed_)
00773     throw CORBA::OBJECT_NOT_EXIST ();
00774 
00775   // If we received compound name, resolve it to get the context in
00776   // which the rebinding should take place, then perform the rebinding
00777   // on target context.
00778   if (name_len > 1)
00779     {
00780       // This had been a read on the file so now we are done with it
00781       flck.release();
00782 
00783       CosNaming::NamingContext_var context =
00784         get_context (n);
00785 
00786       CosNaming::Name simple_name;
00787       simple_name.length (1);
00788       simple_name[0] = n[name_len - 1];
00789       context->rebind (simple_name, obj);
00790     }
00791   // If we received a simple name, we need to rebind it in this
00792   // context.
00793   else
00794     {
00795       int result = this->context_->rebind (n[0].id,
00796                                            n[0].kind,
00797                                            obj,
00798                                            CosNaming::nobject);
00799 
00800       // Check for error conditions.
00801       if (result == -1)
00802         throw CORBA::INTERNAL ();
00803 
00804       else if (result == -2)
00805         throw CosNaming::NamingContext::NotFound(
00806           CosNaming::NamingContext::not_object,
00807           n);
00808 
00809       this->Write(flck.peer());
00810     }
00811 }
00812 
00813 void
00814 TAO_Storable_Naming_Context::bind_context (const CosNaming::Name &n,
00815                                            CosNaming::NamingContext_ptr nc)
00816 {
00817   ACE_TRACE("TAO_Storable_Naming_Context::bind_context");
00818   // Get the length of the name.
00819   CORBA::ULong name_len = n.length ();
00820 
00821   // Check for invalid name.
00822   if (name_len == 0)
00823     throw CosNaming::NamingContext::InvalidName();
00824 
00825   // Do not allow binding of nil context reference.
00826   if (CORBA::is_nil (nc))
00827     throw CORBA::BAD_PARAM ();
00828 
00829   // we didn't need a lock to check the input arg, but now we do
00830   ACE_GUARD_THROW_EX (ACE_SYNCH_RECURSIVE_MUTEX, ace_mon,
00831                       this->lock_,
00832                       CORBA::INTERNAL ());
00833 
00834   // Open the backing file
00835   File_Open_Lock_and_Check flck(this, name_len > 1 ? "r" : "rw");
00836 
00837   // Check to make sure this object didn't have <destroy> method
00838   // invoked on it.
00839   if (this->destroyed_)
00840     throw CORBA::OBJECT_NOT_EXIST ();
00841 
00842   // If we received compound name, resolve it to get the context in
00843   // which the binding should take place, then perform the binding
00844   // on target context.
00845   if (name_len > 1)
00846     {
00847       // This had been a read on the file so now we are done with it
00848       flck.release();
00849 
00850       CosNaming::NamingContext_var context =
00851         get_context (n);
00852 
00853       CosNaming::Name simple_name;
00854       simple_name.length (1);
00855       simple_name[0] = n[name_len - 1];
00856       context->bind_context (simple_name, nc);
00857     }
00858   // If we received a simple name, we need to bind it in this context.
00859   else
00860     {
00861       // Try binding the name.
00862       int result = this->context_->bind (n[0].id,
00863                                          n[0].kind,
00864                                          nc,
00865                                          CosNaming::ncontext);
00866       if (result == 1)
00867         throw CosNaming::NamingContext::AlreadyBound();
00868 
00869       // Something went wrong with the internal structure
00870       else if (result == -1)
00871         throw CORBA::INTERNAL ();
00872 
00873       this->Write(flck.peer());
00874     }
00875 }
00876 
00877 void
00878 TAO_Storable_Naming_Context::rebind_context (const CosNaming::Name &n,
00879                                          CosNaming::NamingContext_ptr nc)
00880 {
00881   ACE_TRACE("rebind_context");
00882   // Get the length of the name.
00883   CORBA::ULong name_len = n.length ();
00884 
00885   // Check for invalid name.
00886   if (name_len == 0)
00887     throw CosNaming::NamingContext::InvalidName();
00888 
00889   // we didn't need a lock to check the input arg, but now we do
00890   ACE_GUARD_THROW_EX (ACE_SYNCH_RECURSIVE_MUTEX, ace_mon,
00891                       this->lock_,
00892                       CORBA::INTERNAL ());
00893 
00894   // Open the backing file
00895   File_Open_Lock_and_Check flck(this, name_len > 1 ? "r" : "rw");
00896 
00897   // Check to make sure this object didn't have <destroy> method
00898   // invoked on it.
00899   if (this->destroyed_)
00900     throw CORBA::OBJECT_NOT_EXIST ();
00901 
00902   // If we received compound name, resolve it to get the context in
00903   // which the rebinding should take place, then perform the rebinding
00904   // on target context.
00905   if (name_len > 1)
00906     {
00907       // This had been a read on the file so now we are done with it
00908       flck.release();
00909 
00910       CosNaming::NamingContext_var context =
00911         get_context (n);
00912 
00913       CosNaming::Name simple_name;
00914       simple_name.length (1);
00915       simple_name[0] = n[name_len - 1];
00916       context->rebind_context (simple_name, nc);
00917     }
00918   // If we received a simple name, we need to rebind it in this
00919   // context.
00920   else
00921     {
00922       int result = this->context_->rebind (n[0].id,
00923                                            n[0].kind,
00924                                            nc,
00925                                            CosNaming::ncontext);
00926       // Check for error conditions.
00927       if (result == -1)
00928         throw CORBA::INTERNAL ();
00929       else if (result == -2)
00930         throw CosNaming::NamingContext::NotFound(
00931           CosNaming::NamingContext::not_context,
00932           n);
00933 
00934       this->Write(flck.peer());
00935     }
00936 }
00937 
00938 CORBA::Object_ptr
00939 TAO_Storable_Naming_Context::resolve (const CosNaming::Name& n)
00940 {
00941   ACE_TRACE("resolve");
00942   // Get the length of the name.
00943   CORBA::ULong name_len = n.length ();
00944 
00945   // Check for invalid name.
00946   if (name_len == 0)
00947     throw CosNaming::NamingContext::InvalidName();
00948 
00949   // we didn't need a lock to check the input arg, but now we do
00950   ACE_GUARD_THROW_EX (ACE_SYNCH_RECURSIVE_MUTEX, ace_mon, this->lock_,
00951                       CORBA::INTERNAL ());
00952 
00953   // Open the backing file
00954   File_Open_Lock_and_Check flck(this, "r");
00955 
00956   // Check to make sure this object didn't have <destroy> method
00957   // invoked on it.
00958   if (this->destroyed_)
00959     throw CORBA::OBJECT_NOT_EXIST ();
00960 
00961   // Resolve the first component of the name.
00962   flck.release();
00963 
00964   // Stores the binding type for the first name component.
00965   CosNaming::BindingType type;
00966   // Stores the object reference bound to the first name component.
00967   CORBA::Object_ptr obj = CORBA::Object::_nil ();
00968 
00969   if (this->context_->find (n[0].id,
00970                             n[0].kind,
00971                             obj,
00972                             type) == -1)
00973     throw CosNaming::NamingContext::NotFound(
00974       CosNaming::NamingContext::missing_node,
00975       n);
00976 
00977   // Store the value in var to avoid memory leaks.
00978   CORBA::Object_var result = obj;
00979 
00980   // If the name we have to resolve is a compound name, we need to
00981   // resolve it recursively.
00982   if (name_len > 1)
00983     {
00984       CosNaming::NamingContext_var context =
00985         CosNaming::NamingContext::_nil ();
00986 
00987       if (type == CosNaming::ncontext)
00988         {
00989           // Narrow to NamingContext.
00990           context = CosNaming::NamingContext::_narrow (result.in ());
00991         }
00992       else
00993         // The first name component wasn't bound to a NamingContext.
00994         throw CosNaming::NamingContext::NotFound(
00995           CosNaming::NamingContext::not_context,
00996           n);
00997 
00998       // If narrow failed...
00999       if (CORBA::is_nil (context.in ()))
01000         throw CosNaming::NamingContext::NotFound(
01001           CosNaming::NamingContext::not_context,
01002           n);
01003       else
01004         {
01005           // Successfully resolved the first name component, need to
01006           // recursively call resolve on <n> without the first component.
01007 
01008           // We need a name just like <n> but without the first
01009           // component.  Instead of copying data we can reuse <n>'s
01010           // buffer since we will only be using it for 'in' parameters
01011           // (no modifications).
01012           CosNaming::Name rest_of_name
01013             (n.maximum () - 1,
01014              n.length () - 1,
01015              const_cast<CosNaming::NameComponent*> (n.get_buffer ()) + 1);
01016 
01017           // If there are any exceptions, they will propagate up.
01018           return context->resolve (rest_of_name);
01019         }
01020     }
01021   // If the name we had to resolve was simple, we just need to return
01022   // the result.
01023   return result._retn ();
01024 }
01025 
01026 void
01027 TAO_Storable_Naming_Context::unbind (const CosNaming::Name& n)
01028 {
01029   ACE_TRACE("unbind");
01030   // Get the length of the name.
01031   CORBA::ULong name_len = n.length ();
01032 
01033   // Check for invalid name.
01034   if (name_len == 0)
01035     throw CosNaming::NamingContext::InvalidName();
01036 
01037   // we didn't need a lock to check the input arg, but now we do
01038   ACE_GUARD_THROW_EX (ACE_SYNCH_RECURSIVE_MUTEX, ace_mon,
01039                       this->lock_,
01040                       CORBA::INTERNAL ());
01041 
01042   // Open the backing file
01043   File_Open_Lock_and_Check flck(this, name_len > 1 ? "r" : "rw");
01044 
01045   // Check to make sure this object didn't have <destroy> method
01046   // invoked on it.
01047   if (this->destroyed_)
01048     throw CORBA::OBJECT_NOT_EXIST ();
01049 
01050   // If we received compound name, resolve it to get the context in
01051   // which the unbinding should take place, then perform the unbinding
01052   // on target context.
01053   if (name_len > 1)
01054     {
01055       // This had been a read on the file so now we are done with it
01056       flck.release();
01057 
01058       CosNaming::NamingContext_var context =
01059         get_context (n);
01060 
01061       CosNaming::Name simple_name;
01062       simple_name.length (1);
01063       simple_name[0] = n[name_len - 1];
01064       context->unbind (simple_name);
01065     }
01066   // If we received a simple name, we need to unbind it in this
01067   // context.
01068   else
01069     {
01070       if (this->context_->unbind (n[0].id,
01071                                   n[0].kind) == -1)
01072         throw CosNaming::NamingContext::NotFound(
01073           CosNaming::NamingContext::missing_node,
01074           n);
01075 
01076       this->Write(flck.peer());
01077     }
01078 }
01079 
01080 CosNaming::NamingContext_ptr
01081 TAO_Storable_Naming_Context::bind_new_context (const CosNaming::Name& n)
01082 {
01083   ACE_TRACE("bind_new_context");
01084   // Get the length of the name.
01085   CORBA::ULong name_len = n.length ();
01086 
01087   // Check for invalid name.
01088   if (name_len == 0)
01089     throw CosNaming::NamingContext::InvalidName();
01090 
01091   ACE_GUARD_THROW_EX (ACE_SYNCH_RECURSIVE_MUTEX,
01092                       ace_mon,
01093                       this->lock_,
01094                       CORBA::INTERNAL ());
01095 
01096   // Check to make sure this object didn't have <destroy> method
01097   // invoked on it.
01098   if (this->destroyed_)
01099     throw CORBA::OBJECT_NOT_EXIST ();
01100 
01101   // Open the backing file
01102   File_Open_Lock_and_Check flck(this, name_len > 1 ? "r" : "rw");
01103 
01104   // Check to make sure this object didn't have <destroy> method
01105   // invoked on it.
01106   if (this->destroyed_)
01107     throw CORBA::OBJECT_NOT_EXIST ();
01108 
01109   // If we received compound name, resolve it to get the context in
01110   // which the binding should take place, then perform the operation on
01111   // target context.
01112   if (name_len > 1)
01113     {
01114       // This had been a read on the file so now we are done with it
01115       flck.release();
01116 
01117       CosNaming::NamingContext_var context =
01118         get_context (n);
01119 
01120       CosNaming::Name simple_name;
01121       simple_name.length (1);
01122       simple_name[0] = n[name_len - 1];
01123       return context->bind_new_context (simple_name);
01124     }
01125   // If we received a simple name, we need to bind it in this context.
01126 
01127   // This had been a read on the file so now we are done with it
01128   flck.release();
01129 
01130   // Stores our new Naming Context.
01131   CosNaming::NamingContext_var result =
01132     CosNaming::NamingContext::_nil ();
01133 
01134   // Create new context.
01135   result = new_context ();
01136 
01137   // Bind the new context to the name.
01138   try
01139     {
01140       bind_context (n,
01141                     result.in ());
01142     }
01143   catch (const CORBA::Exception&)
01144     {
01145       {
01146         try
01147           {
01148             result->destroy ();
01149           }
01150         catch (const CORBA::Exception&)
01151           {
01152             // Do nothing?
01153           }
01154       }
01155       // Re-raise the exception in bind_context()
01156       throw;
01157     }
01158   return result._retn ();
01159 }
01160 
01161 void
01162 TAO_Storable_Naming_Context::destroy (void)
01163 {
01164   ACE_TRACE("destroy");
01165   ACE_GUARD_THROW_EX (ACE_SYNCH_RECURSIVE_MUTEX,
01166                       ace_mon,
01167                       this->lock_,
01168                       CORBA::INTERNAL ());
01169 
01170   // Open the backing file
01171   File_Open_Lock_and_Check flck(this, "rw");
01172 
01173   // Check to make sure this object didn't have <destroy> method
01174   // invoked on it.
01175   if (this->destroyed_)
01176     throw CORBA::OBJECT_NOT_EXIST ();
01177 
01178   if (this->context_->current_size () != 0)
01179     throw CosNaming::NamingContext::NotEmpty();
01180 
01181   // Destroy is a no-op on a root context.
01182   if (root ())
01183     return;
01184 
01185   else
01186     {
01187       this->destroyed_ = 2;
01188 
01189       // Remove self from POA.  Because of reference counting, the POA
01190       // will automatically delete the servant when all pending requests
01191       // on this servant are complete.
01192 
01193       PortableServer::POA_var poa =
01194         this->_default_POA ();
01195 
01196       PortableServer::ObjectId_var id =
01197         PortableServer::string_to_ObjectId (poa_id_.fast_rep ());
01198 
01199 
01200       poa->deactivate_object (id.in ());
01201 
01202       this->Write(flck.peer());
01203     }
01204 }
01205 
01206 
01207 void
01208 TAO_Storable_Naming_Context::bind (const CosNaming::Name& n,
01209                                CORBA::Object_ptr obj)
01210 {
01211   ACE_TRACE("TAO_Storable_Naming_Context::bind");
01212   // Get the length of the name.
01213   CORBA::ULong name_len = n.length ();
01214 
01215   // Check for invalid name.
01216   if (name_len == 0)
01217     throw CosNaming::NamingContext::InvalidName();
01218 
01219   // we didn't need a lock to check the input arg, but now we do
01220   ACE_GUARD_THROW_EX (ACE_SYNCH_RECURSIVE_MUTEX, ace_mon,
01221                       this->lock_,
01222                       CORBA::INTERNAL ());
01223 
01224   // Open the backing file
01225   File_Open_Lock_and_Check flck(this, name_len > 1 ? "r" : "rw");
01226 
01227   // Check to make sure this object didn't have <destroy> method
01228   // invoked on it.
01229   if (this->destroyed_)
01230     throw CORBA::OBJECT_NOT_EXIST ();
01231 
01232   // If we received compound name, resolve it to get the context in
01233   // which the binding should take place, then perform the binding
01234   // on target context.
01235   if (name_len > 1)
01236     {
01237       // This had been a read on the file so now we are done with it
01238       flck.release();
01239 
01240       CosNaming::NamingContext_var context =
01241         get_context (n);
01242 
01243       CosNaming::Name simple_name;
01244       simple_name.length (1);
01245       simple_name[0] = n[name_len - 1];
01246       context->bind (simple_name, obj);
01247     }
01248   // If we received a simple name, we need to bind it in this context.
01249   else
01250     {
01251       // Try binding the name.
01252       int result = this->context_->bind (n[0].id,
01253                                          n[0].kind,
01254                                          obj,
01255                                          CosNaming::nobject);
01256       if (result == 1)
01257         throw CosNaming::NamingContext::AlreadyBound();
01258 
01259       // Something went wrong with the internal structure
01260       else if (result == -1)
01261         throw CORBA::INTERNAL ();
01262 
01263       this->Write(flck.peer());
01264     }
01265 }
01266 
01267 
01268 void
01269 TAO_Storable_Naming_Context::list (CORBA::ULong how_many,
01270                                    CosNaming::BindingList_out &bl,
01271                                    CosNaming::BindingIterator_out &bi)
01272 {
01273   ACE_TRACE("list");
01274   // Allocate nil out parameters in case we won't be able to complete
01275   // the operation.
01276   bi = CosNaming::BindingIterator::_nil ();
01277   ACE_NEW_THROW_EX (bl,
01278                     CosNaming::BindingList (0),
01279                     CORBA::NO_MEMORY ());
01280 
01281   // Obtain a lock before we proceed with the operation.
01282   ACE_GUARD_THROW_EX (ACE_SYNCH_RECURSIVE_MUTEX,
01283                       ace_mon,
01284                       this->lock_,
01285                       CORBA::INTERNAL ());
01286 
01287   // Open the backing file
01288   File_Open_Lock_and_Check flck(this, "r");
01289 
01290   // Check to make sure this object didn't have <destroy> method
01291   // invoked on it.
01292   if (this->destroyed_)
01293     throw CORBA::OBJECT_NOT_EXIST ();
01294 
01295   // We have the map in memory, let the disk go
01296   flck.release();
01297 
01298   // Dynamically allocate iterator for traversing the underlying hash map.
01299   HASH_MAP::ITERATOR *hash_iter = 0;
01300   ACE_NEW_THROW_EX (hash_iter,
01301                     HASH_MAP::ITERATOR (storable_context_->map ()),
01302                     CORBA::NO_MEMORY ());
01303 
01304   // Store <hash_iter temporarily in auto pointer, in case we'll have
01305   // some failures and throw an exception.
01306   ACE_Auto_Basic_Ptr<HASH_MAP::ITERATOR> temp (hash_iter);
01307 
01308   // Silliness below is required because of broken old g++!!!  E.g.,
01309   // without it, we could have just said HASH_MAP::ITERATOR everywhere we use ITER_DEF.
01310   typedef ACE_Hash_Map_Manager<TAO_Storable_ExtId,
01311                                TAO_Storable_IntId,
01312                                ACE_Null_Mutex>::ITERATOR ITER_DEF;
01313   typedef ACE_Hash_Map_Manager<TAO_Storable_ExtId,
01314                                TAO_Storable_IntId,
01315                                ACE_Null_Mutex>::ENTRY ENTRY_DEF;
01316 
01317   // Typedef to the type of BindingIterator servant for ease of use.
01318   typedef TAO_Bindings_Iterator<ITER_DEF, ENTRY_DEF> ITER_SERVANT;
01319 
01320   // A pointer to BindingIterator servant.
01321   ITER_SERVANT *bind_iter = 0;
01322 
01323   // Number of bindings that will go into the BindingList <bl>.
01324   CORBA::ULong n;
01325 
01326   // Calculate number of bindings that will go into <bl>.
01327   if (this->context_->current_size () > how_many)
01328     n = how_many;
01329   else
01330     n = static_cast<CORBA::ULong> (this->context_->current_size ());
01331 
01332   // Use the hash map iterator to populate <bl> with bindings.
01333   bl->length (n);
01334 
01335   ENTRY_DEF *hash_entry = 0;
01336 
01337   for (CORBA::ULong i = 0; i < n; i++)
01338     {
01339       hash_iter->next (hash_entry);
01340       hash_iter->advance ();
01341 
01342       if (ITER_SERVANT::populate_binding (hash_entry, bl[i]) == 0)
01343           throw CORBA::NO_MEMORY();
01344     }
01345 
01346   // Now we are done with the BindingsList, and we can follow up on
01347   // the BindingIterator business.
01348 
01349   // If we do not need to pass back BindingIterator.
01350   if (this->context_->current_size () <= how_many)
01351     return;
01352   else
01353     {
01354       //  ***  This is a problem.  Is there an exception we can throw? ***
01355       ACE_UNUSED_ARG (bind_iter);
01356       throw CORBA::NO_IMPLEMENT ();
01357 
01358 #if 0
01359       // Create a BindingIterator for return.
01360       ACE_NEW_THROW_EX (bind_iter,
01361                         ITER_SERVANT (this, hash_iter,
01362                                       this->poa_.in (), this->lock_),
01363                         CORBA::NO_MEMORY ());
01364 
01365       // Release <hash_iter> from auto pointer, and start using
01366       // reference counting to control our servant.
01367       temp.release ();
01368       PortableServer::ServantBase_var iter = bind_iter;
01369 
01370       // Increment reference count on this Naming Context, so it doesn't get
01371       // deleted before the BindingIterator servant gets deleted.
01372       interface_->_add_ref ();
01373 
01374       // Register with the POA.
01375       char poa_id[BUFSIZ];
01376       ACE_OS::sprintf (poa_id,
01377                        "%s_%d",
01378                        this->poa_id_.c_str (),
01379                        this->counter_++);
01380       PortableServer::ObjectId_var id =
01381         PortableServer::string_to_ObjectId (poa_id);
01382 
01383       this->poa_->activate_object_with_id (id.in (),
01384                                            bind_iter);
01385 
01386       bi = bind_iter->_this ();
01387 #endif  /* 0 */
01388     }
01389 }
01390 
01391 TAO_END_VERSIONED_NAMESPACE_DECL
01392 
01393 #include "orbsvcs/Naming/Naming_Service_Container.h"
01394 
01395 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
01396 
01397 CosNaming::NamingContext_ptr TAO_Storable_Naming_Context::recreate_all(
01398                                CORBA::ORB_ptr orb,
01399                                PortableServer::POA_ptr poa,
01400                                const char *poa_id,
01401                                size_t context_size,
01402                                int reentering,
01403                                TAO_Naming_Service_Persistence_Factory *factory,
01404                                const ACE_TCHAR *persistence_directory,
01405                                int use_redundancy)
01406 {
01407   ACE_TRACE("recreate_all");
01408 
01409   ACE_UNUSED_ARG (reentering);
01410 
01411   // Whether we are redundant is global
01412   redundant_ = use_redundancy;
01413 
01414   // Save the root name for later use
01415   root_name_ = poa_id;
01416 
01417   // Create a new context.
01418   TAO_Storable_Naming_Context *new_context = 0;
01419   CosNaming::NamingContext_var result =
01420     make_new_context (orb,
01421                       poa,
01422                       poa_id,
01423                       context_size,
01424                       factory,
01425                       persistence_directory,
01426                       &new_context);
01427 
01428   // Now does this already exist on disk?
01429   ACE_TString file_name(persistence_directory);
01430   file_name += ACE_TEXT("/");
01431   file_name += ACE_TEXT_CHAR_TO_TCHAR(poa_id);
01432   ACE_Auto_Ptr<TAO_Storable_Base> fl (factory->create_stream(ACE_TEXT_ALWAYS_CHAR(file_name.c_str()), ACE_TEXT("r")));
01433   if (fl->exists())
01434   {
01435     // Load the map from disk
01436     File_Open_Lock_and_Check flck(new_context, "r");
01437   }
01438   else
01439   {
01440     // Since this is a new context, make and empty map in it
01441     ACE_NEW_THROW_EX (new_context->storable_context_,
01442                       TAO_Storable_Bindings_Map (context_size,orb),
01443                       CORBA::NO_MEMORY ());
01444     new_context->context_ = new_context->storable_context_;
01445     File_Open_Lock_and_Check flck(new_context, "wc");
01446     new_context->Write(flck.peer());
01447   }
01448 
01449   // build the global file name
01450   file_name += ACE_TEXT("_global");
01451 
01452   // Create the stream for the counter used to uniquely creat context names
01453   gfl_.reset(factory->create_stream(ACE_TEXT_ALWAYS_CHAR(file_name.c_str()), ACE_TEXT("crw")));
01454   if (gfl_->open() != 0)
01455     {
01456       delete gfl_.release();
01457       throw CORBA::PERSIST_STORE();
01458     }
01459 
01460   // get the counter from disk
01461   TAO_NS_Persistence_Global global;
01462   *gfl_.get() >> global;
01463   if (!gfl_.get ()->good () &&
01464       gfl_.get ()->rdstate () != TAO_Storable_Base::eofbit)
01465     {
01466       gfl_.get ()->clear ();
01467       throw CORBA::INTERNAL ();
01468     }
01469   gcounter_ = global.counter();
01470   if(redundant_) gfl_->close();
01471 
01472   return result._retn ();
01473 }
01474 
01475 TAO_END_VERSIONED_NAMESPACE_DECL

Generated on Sun Jan 27 16:15:32 2008 for TAO_CosNaming by doxygen 1.3.6