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

Generated on Tue Feb 2 17:49:05 2010 for TAO_CosNaming by  doxygen 1.4.7