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

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