Persistent_Naming_Context.cpp

Go to the documentation of this file.
00001 #include "orbsvcs/Naming/Persistent_Naming_Context.h"
00002 #include "orbsvcs/Naming/Persistent_Context_Index.h"
00003 #include "orbsvcs/Naming/Bindings_Iterator_T.h"
00004 #include "ace/OS_NS_stdio.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 
00018 ACE_RCSID (Naming,
00019            Persistent_Naming_Context,
00020            "$Id: Persistent_Naming_Context.cpp 76880 2007-02-02 16:22:17Z johnnyw $")
00021 
00022 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00023 
00024 int
00025 TAO_Persistent_Bindings_Map::unbind (const char *id,
00026                                      const char *kind)
00027 {
00028   TAO_Persistent_ExtId name (id, kind);
00029   TAO_Persistent_IntId entry;
00030   if (this->map_->unbind (name, entry, this->allocator_) != 0)
00031     return -1;
00032   else
00033     {
00034       // Free up the memory we allocated in shared_bind().  Note that
00035       // this assumes that the "ref" pointer comes first and that
00036       // the ref, id and kind are contiguously allocated (see
00037       // shared_bind() for details).
00038       this->allocator_->free ((void *) (entry.ref_));
00039       return 0;
00040     }
00041 }
00042 
00043 int
00044 TAO_Persistent_Bindings_Map::bind (const char *id,
00045                                    const char *kind,
00046                                    CORBA::Object_ptr obj,
00047                                    CosNaming::BindingType type)
00048 {
00049   return this->shared_bind (id, kind, obj, type, 0);
00050 }
00051 
00052 int
00053 TAO_Persistent_Bindings_Map::rebind (const char *id,
00054                                      const char *kind,
00055                                      CORBA::Object_ptr obj,
00056                                      CosNaming::BindingType type)
00057 {
00058   return this->shared_bind (id, kind, obj, type, 1);
00059 }
00060 
00061 int
00062 TAO_Persistent_Bindings_Map::find (const char *id,
00063                                    const char *kind,
00064                                    CORBA::Object_ptr & obj,
00065                                    CosNaming::BindingType &type)
00066 {
00067   TAO_Persistent_ExtId name (id, kind);
00068   TAO_Persistent_IntId entry;
00069 
00070   if (this->map_->find (name,
00071                         entry,
00072                         this->allocator_) != 0)
00073     return -1;
00074   else
00075     {
00076       obj = orb_->string_to_object (entry.ref_);
00077       type = entry.type_;
00078 
00079       return 0;
00080     }
00081 }
00082 
00083 TAO_Persistent_Bindings_Map::TAO_Persistent_Bindings_Map (CORBA::ORB_ptr orb)
00084   : allocator_ (0),
00085     map_ (0),
00086     orb_ (CORBA::ORB::_duplicate (orb))
00087 {
00088 }
00089 
00090 TAO_Persistent_Bindings_Map::~TAO_Persistent_Bindings_Map (void)
00091 {
00092 }
00093 
00094 void
00095 TAO_Persistent_Bindings_Map::destroy (void)
00096 {
00097   this->map_->ACE_Hash_Map_With_Allocator<TAO_Persistent_ExtId, TAO_Persistent_IntId>::~ACE_Hash_Map_With_Allocator ();
00098   this->allocator_->free (map_);
00099 }
00100 
00101 TAO_Persistent_Bindings_Map::HASH_MAP *
00102 TAO_Persistent_Bindings_Map::map (void)
00103 {
00104   return this->map_;
00105 }
00106 
00107 size_t
00108 TAO_Persistent_Bindings_Map::total_size (void)
00109 {
00110   return this->map_->total_size ();
00111 }
00112 
00113 size_t
00114 TAO_Persistent_Bindings_Map::current_size (void)
00115 {
00116   return map_->current_size ();
00117 }
00118 
00119 int
00120 TAO_Persistent_Bindings_Map::open (size_t hash_table_size,
00121                                    ACE_Allocator *alloc)
00122 {
00123   allocator_ = alloc;
00124 
00125   // Use allocator to allocate space for the hash map.
00126   void *hash_map = 0;
00127   size_t map_size = sizeof (HASH_MAP);
00128   hash_map = this->allocator_->malloc (map_size);
00129 
00130   // If allocation failed ...
00131   if (hash_map == 0)
00132     return -1;
00133 
00134   // Initialize allocated hash map through placement new.
00135   if (open_helper (hash_table_size, hash_map) == -1)
00136     this->allocator_->free (hash_map);
00137 
00138   return 0;
00139 }
00140 
00141 int
00142 TAO_Persistent_Bindings_Map::open_helper (size_t hash_table_size,
00143                                           void *buffer)
00144 {
00145   this->map_ = new (buffer) HASH_MAP (hash_table_size, this->allocator_);
00146   return 0;
00147 }
00148 
00149 void
00150 TAO_Persistent_Bindings_Map::set (HASH_MAP *map,
00151                                   ACE_Allocator *alloc)
00152 {
00153   allocator_ = alloc;
00154   map_ = map;
00155 }
00156 
00157 int
00158 TAO_Persistent_Bindings_Map::shared_bind (const char * id,
00159                                           const char * kind,
00160                                           CORBA::Object_ptr obj,
00161                                           CosNaming::BindingType type,
00162                                           int rebind)
00163 {
00164   // Obtain a stringified ior of <obj> (i.e., the representation we can store).
00165   CORBA::String_var ref = orb_->object_to_string (obj);
00166 
00167   // Calculate and allocate the memory we need to store this name to
00168   // object binding.
00169   size_t id_len = ACE_OS::strlen (id) + 1;
00170   size_t kind_len = ACE_OS::strlen (kind) + 1;
00171   size_t ref_len = ACE_OS::strlen (ref.in ()) + 1;
00172   size_t total_len = id_len + kind_len + ref_len;
00173   char *ptr = (char *) this->allocator_->malloc (total_len);
00174 
00175   // Allocation failed - bail out.
00176   if (ptr == 0)
00177     return -1;
00178 
00179   // Allocation succeded - place the data into the allocated memory
00180   // and procceed.
00181   else
00182     {
00183       // Note that the <ref> *must* come first to make sure we can
00184       // retrieve this pointer later on in unbind().
00185       char * ref_ptr = ptr;
00186       char * id_ptr =  ptr + ref_len;
00187       char * kind_ptr = ptr + ref_len + id_len;
00188       ACE_OS::strcpy (ref_ptr, ref.in ());
00189       ACE_OS::strcpy (id_ptr, id);
00190       ACE_OS::strcpy (kind_ptr, kind);
00191 
00192       TAO_Persistent_ExtId new_name (id_ptr, kind_ptr);
00193       TAO_Persistent_IntId new_entry (ref_ptr, type);
00194       int result = -1;
00195 
00196       if (rebind == 0)
00197         {
00198           // Do a normal bind.  This will fail if there's already an
00199           // <new_internal> with the same name.
00200           result = this->map_->bind (new_name, new_entry, this->allocator_);
00201 
00202           if (result == 1)
00203             {
00204               // Entry already existed so bind failed. Free our
00205               // dynamically allocated  memory.
00206               this->allocator_->free ((void *) ptr);
00207               return result;
00208             }
00209         }
00210       else
00211         // Rebind.
00212         {
00213           TAO_Persistent_ExtId old_name;
00214           TAO_Persistent_IntId old_entry;
00215 
00216           // Check that the types of old and new entries match.
00217           if (this->map_->find (new_name,
00218                                 old_entry,
00219                                 this->allocator_) == 0
00220               && type != old_entry.type_)
00221             result = -2;
00222 
00223           // If types match, perform rebind.
00224           else
00225             result = this->map_->rebind (new_name, new_entry,
00226                                          old_name, old_entry,
00227                                          this->allocator_);
00228           if (result == 1)
00229             {
00230               // Free up the old binding's memory, if it was replaced.
00231               // Note, this assumes that the "ref" pointer comes
00232               // first, and that the id, kind, and ref are contiguously
00233               // allocated (see beginning of this method for details).
00234               this->allocator_->free ((void *) old_entry.ref_);
00235             }
00236         }
00237 
00238       // Check for failures, and clean up dynamically allocated memory
00239       // if necessary.
00240       if (result < 0)
00241         this->allocator_->free ((void *) ptr);
00242 
00243       else
00244         // If bind() or rebind() succeeded, they will automatically sync
00245         // up the map manager entry.  However, we must sync up our
00246         // name/value memory.
00247         this->allocator_->sync (ptr, total_len);
00248 
00249       return result;
00250     }
00251 }
00252 
00253 TAO_Persistent_Naming_Context::TAO_Persistent_Naming_Context (PortableServer::POA_ptr poa,
00254                                                               const char *poa_id,
00255                                                               TAO_Persistent_Context_Index *context_index)
00256 
00257   : TAO_Hash_Naming_Context (poa,
00258                              poa_id),
00259     counter_ (0),
00260     persistent_context_ (0),
00261     index_ (context_index)
00262 {
00263   ACE_NEW (this->persistent_context_,
00264            TAO_Persistent_Bindings_Map (context_index->orb ()));
00265 
00266   // Set the superclass pointer.
00267   context_ = persistent_context_;
00268 }
00269 
00270 TAO_Persistent_Naming_Context::TAO_Persistent_Naming_Context (PortableServer::POA_ptr poa,
00271                                                               const char *poa_id,
00272                                                               TAO_Persistent_Context_Index *context_index,
00273                                                               HASH_MAP *map,
00274                                                               ACE_UINT32 *counter)
00275   : TAO_Hash_Naming_Context (poa,
00276                              poa_id),
00277     counter_ (counter),
00278     persistent_context_ (0),
00279     index_ (context_index)
00280 {
00281   ACE_NEW (this->persistent_context_,
00282            TAO_Persistent_Bindings_Map (context_index->orb ()));
00283 
00284   // Set the superclass pointer.
00285   context_ = persistent_context_;
00286 
00287   persistent_context_->set (map, index_->allocator ());
00288 }
00289 
00290 int
00291 TAO_Persistent_Naming_Context::init (size_t hash_table_size)
00292 {
00293   return persistent_context_->open (hash_table_size, index_->allocator ());
00294 }
00295 
00296 TAO_Persistent_Naming_Context::~TAO_Persistent_Naming_Context (void)
00297 {
00298   // Perform appropriate cleanup based on the destruction level specified.
00299 
00300   if (this->destroyed_ > 1)
00301     {
00302       // Remove ourselves from context index.
00303       index_->unbind (poa_id_.c_str ());
00304       // Remove the underlying data structure from persistent storage.
00305       persistent_context_->destroy ();
00306     }
00307   else if (this->destroyed_ == 1)
00308     // Remove the underlying data structure from persistent storage.
00309     persistent_context_->destroy ();
00310 }
00311 
00312 void
00313 TAO_Persistent_Naming_Context::set_cleanup_level (int level)
00314 {
00315   this->destroyed_ = level;
00316 }
00317 
00318 CosNaming::NamingContext_ptr
00319 TAO_Persistent_Naming_Context::make_new_context (PortableServer::POA_ptr poa,
00320                                                  const char *poa_id,
00321                                                  size_t context_size,
00322                                                  TAO_Persistent_Context_Index * ind)
00323 {
00324   // Store the stub we will return here.
00325   CosNaming::NamingContext_var result;
00326 
00327   // Put together a servant for the new Naming Context.
00328 
00329   TAO_Persistent_Naming_Context *context_impl = 0;
00330   ACE_NEW_THROW_EX (context_impl,
00331                     TAO_Persistent_Naming_Context (poa,
00332                                                    poa_id,
00333                                                    ind),
00334                     CORBA::NO_MEMORY ());
00335 
00336   // Put <context_impl> into the auto pointer temporarily, in case next
00337   // allocation fails.
00338   ACE_Auto_Basic_Ptr<TAO_Persistent_Naming_Context> temp (context_impl);
00339 
00340   if (context_impl->init (context_size) == -1)
00341     throw CORBA::NO_MEMORY ();
00342 
00343   // Insure appropriate cleanup in case of exception conditions ahead.
00344   context_impl->set_cleanup_level (1);
00345 
00346   // Register with the index of Naming Contexts.
00347   if (ind->bind (context_impl->poa_id_.c_str (),
00348                  context_impl->counter_,
00349                  context_impl->persistent_context_->map ()) == -1)
00350     throw CORBA::INTERNAL ();
00351 
00352   // Insure appropriate cleanup in case of exception conditions ahead.
00353   context_impl->set_cleanup_level (2);
00354 
00355   TAO_Naming_Context *context = 0;
00356   ACE_NEW_THROW_EX (context,
00357                     TAO_Naming_Context (context_impl),
00358                     CORBA::NO_MEMORY ());
00359 
00360   // Let <implementation> know about it's <interface>.
00361   context_impl->interface (context);
00362 
00363   // Release auto pointer, and start using reference counting to
00364   // control our servant.
00365   temp.release ();
00366   PortableServer::ServantBase_var s = context;
00367 
00368   // Register the new context with the POA.
00369   PortableServer::ObjectId_var id =
00370     PortableServer::string_to_ObjectId (poa_id);
00371 
00372   poa->activate_object_with_id (id.in (),
00373                                 context);
00374 
00375   result = context->_this ();
00376 
00377   // Everything went smoothly, without errors - we don't need any cleanup.
00378   context_impl->set_cleanup_level (0);
00379 
00380   return result._retn ();
00381 }
00382 
00383 CosNaming::NamingContext_ptr
00384 TAO_Persistent_Naming_Context::new_context (void)
00385 {
00386   ACE_GUARD_THROW_EX (TAO_SYNCH_RECURSIVE_MUTEX,
00387                       ace_mon,
00388                       this->lock_,
00389                       CORBA::INTERNAL ());
00390 
00391   // Check to make sure this object didn't have <destroy> method
00392   // invoked on it.
00393   if (this->destroyed_)
00394     throw CORBA::OBJECT_NOT_EXIST ();
00395 
00396   // Generate a POA id for the new context.
00397   char poa_id[BUFSIZ];
00398   ACE_OS::sprintf (poa_id,
00399                    "%s_%d",
00400                    this->poa_id_.c_str (),
00401                    (*this->counter_)++);
00402 
00403   CosNaming::NamingContext_var result =
00404     make_new_context (this->poa_.in (),
00405                       poa_id,
00406                       this->persistent_context_->total_size (),
00407                       this->index_);
00408 
00409   return result._retn ();
00410 }
00411 
00412 void
00413 TAO_Persistent_Naming_Context::list (CORBA::ULong how_many,
00414                                      CosNaming::BindingList_out &bl,
00415                                      CosNaming::BindingIterator_out &bi)
00416 {
00417   // Allocate nil out parameters in case we won't be able to complete
00418   // the operation.
00419   bi = CosNaming::BindingIterator::_nil ();
00420   ACE_NEW_THROW_EX (bl,
00421                     CosNaming::BindingList (0),
00422                     CORBA::NO_MEMORY ());
00423 
00424   // Obtain a lock before we proceed with the operation.
00425   ACE_GUARD_THROW_EX (TAO_SYNCH_RECURSIVE_MUTEX,
00426                       ace_mon,
00427                       this->lock_,
00428                       CORBA::INTERNAL ());
00429 
00430   // Check to make sure this object didn't have <destroy> method
00431   // invoked on it.
00432   if (this->destroyed_)
00433     throw CORBA::OBJECT_NOT_EXIST ();
00434 
00435   // Dynamically allocate hash map iterator.
00436   HASH_MAP::ITERATOR *hash_iter = 0;
00437   ACE_NEW_THROW_EX (hash_iter,
00438                     HASH_MAP::ITERATOR
00439                     (*persistent_context_->map ()),
00440                     CORBA::NO_MEMORY ());
00441 
00442   // Store <hash_iter temporarily in auto pointer, in case we'll have
00443   // some failures and throw an exception.
00444   ACE_Auto_Basic_Ptr<HASH_MAP::ITERATOR> temp (hash_iter);
00445 
00446   // Silliness below is required because of broken old g++!!!  E.g.,
00447   // without it, we could have just said HASH_MAP::ITERATOR everywhere we use ITER_DEF.
00448   typedef ACE_Hash_Map_With_Allocator<TAO_Persistent_ExtId, TAO_Persistent_IntId>::ITERATOR ITER_DEF;
00449   typedef ACE_Hash_Map_With_Allocator<TAO_Persistent_ExtId, TAO_Persistent_IntId>::ENTRY ENTRY_DEF;
00450 
00451   // Typedef to the type of BindingIterator servant for ease of use.
00452   typedef TAO_Bindings_Iterator<ITER_DEF, ENTRY_DEF> ITER_SERVANT;
00453 
00454   // A pointer to BindingIterator servant.
00455   ITER_SERVANT *bind_iter = 0;
00456 
00457   // Number of bindings that will go into the BindingList.
00458   CORBA::ULong n;
00459 
00460   // Calculate number of bindings that will go into bl.
00461   if (this->context_->current_size () > how_many)
00462     n = how_many;
00463   else
00464     n = static_cast<CORBA::ULong> (this->context_->current_size ());
00465 
00466   // Use hash iterator to populate a BindingList with bindings.
00467   bl->length (n);
00468 
00469   ENTRY_DEF *hash_entry = 0;
00470 
00471   for (CORBA::ULong i = 0; i < n; i++)
00472     {
00473       hash_iter->next (hash_entry);
00474       hash_iter->advance ();
00475 
00476       if (ITER_SERVANT::populate_binding (hash_entry, bl[i]) == 0)
00477           throw CORBA::NO_MEMORY();
00478     }
00479 
00480   // Now we are done with the BindingsList, and we can follow up on
00481   // the iterator business.
00482 
00483   // If we do not need to pass back BindingIterator.
00484   if (this->context_->current_size () <= how_many)
00485     return;
00486   else
00487     {
00488       // Create a BindingIterator for return.
00489       ACE_NEW_THROW_EX (bind_iter,
00490                         ITER_SERVANT (this, hash_iter, this->poa_.in (), this->lock_),
00491                         CORBA::NO_MEMORY ());
00492 
00493       // Release <hash_iter> from auto pointer, and start using the
00494       // reference counting to control our servant.
00495       temp.release ();
00496       PortableServer::ServantBase_var iter = bind_iter;
00497 
00498       // Increment reference count on this Naming Context, so it doesn't get
00499       // deleted before the BindingIterator servant gets deleted.
00500       interface_->_add_ref ();
00501 
00502       // Register with the POA.
00503       char poa_id[BUFSIZ];
00504       ACE_OS::sprintf (poa_id,
00505                        "%s_%d",
00506                        this->poa_id_.c_str (),
00507                        (*this->counter_)++);
00508       PortableServer::ObjectId_var id =
00509         PortableServer::string_to_ObjectId (poa_id);
00510 
00511       this->poa_->activate_object_with_id (id.in (),
00512                                            bind_iter);
00513 
00514       bi = bind_iter->_this ();
00515     }
00516 }
00517 
00518 TAO_END_VERSIONED_NAMESPACE_DECL

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