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

Generated on Thu Nov 9 13:57:03 2006 for TAO_CosNaming by doxygen 1.3.6