diff options
-rw-r--r-- | TAO/ChangeLog | 56 | ||||
-rw-r--r-- | TAO/tao/IIOP_Profile.cpp | 28 | ||||
-rw-r--r-- | TAO/tao/IIOP_Transport.cpp | 1 | ||||
-rw-r--r-- | TAO/tao/Makefile.tao | 4 | ||||
-rw-r--r-- | TAO/tao/ORB_Core.cpp | 26 | ||||
-rw-r--r-- | TAO/tao/ORB_Core.h | 7 | ||||
-rw-r--r-- | TAO/tao/ORB_Core.i | 6 | ||||
-rw-r--r-- | TAO/tao/ObjectKey_Table.cpp | 169 | ||||
-rw-r--r-- | TAO/tao/ObjectKey_Table.h | 125 | ||||
-rw-r--r-- | TAO/tao/Profile.cpp | 44 | ||||
-rw-r--r-- | TAO/tao/Profile.h | 12 | ||||
-rw-r--r-- | TAO/tao/Profile.i | 2 | ||||
-rw-r--r-- | TAO/tao/Refcounted_ObjectKey.cpp | 23 | ||||
-rw-r--r-- | TAO/tao/Refcounted_ObjectKey.h | 68 | ||||
-rw-r--r-- | TAO/tao/Refcounted_ObjectKey.inl | 26 | ||||
-rw-r--r-- | TAO/tao/Resource_Factory.cpp | 6 | ||||
-rw-r--r-- | TAO/tao/Resource_Factory.h | 3 | ||||
-rw-r--r-- | TAO/tao/Strategies/DIOP_Profile.cpp | 28 | ||||
-rw-r--r-- | TAO/tao/Strategies/SHMIOP_Profile.cpp | 29 | ||||
-rw-r--r-- | TAO/tao/Strategies/UIOP_Profile.cpp | 28 | ||||
-rw-r--r-- | TAO/tao/default_resource.cpp | 41 | ||||
-rw-r--r-- | TAO/tao/default_resource.h | 4 |
22 files changed, 674 insertions, 62 deletions
diff --git a/TAO/ChangeLog b/TAO/ChangeLog index 648a8544250..a6ffb9ed6cd 100644 --- a/TAO/ChangeLog +++ b/TAO/ChangeLog @@ -1,3 +1,59 @@ +Sun May 11 10:44:56 2003 Balachandran Natarajan <bala@dre.vanderbilt.edu> + + The aim of this checkin is to reduce the runtime memory consumed + by the IORs. Every profile held by the ORB had a copy of the + ObjectKey which added to the memory consumed by the IORs. This + checkin builds a map to store and access the object key + efficiently. + + * tao/ObjectKey_Table.cpp: + * tao/ObjectKey_Table.h: Class that builds a map to store the + object key. + + * tao/Refcounted_ObjectKey.cpp: + * tao/Refcounted_ObjectKey.h: + * tao/Refcounted_ObjectKey.inl: A wrapper class for the object key + that provides reference counting and automatic lifetime + management to the object keys. + + * tao/Profile.cpp: + * tao/Profile.h: + * tao/Profile.i: Have a pointer to the refcounted object key + instead of the actual object key. After unmarshalling the + object key from the profile we now bind it with the ObjectKey + table which returns a pointer to the refcounted object key + which is cached and used during invocation. + + * tao/IIOP_Profile.cpp: + * tao/Strategies/DIOP_Profile.cpp: + * tao/Strategies/SHMIOP_Profile.cpp: + * tao/Strategies/UIOP_Profile.cpp: Use the refcounted object key + pointer instead of object keys. + + * tao/IIOP_Transport.cpp: Removed gratuitious inclusion of the + Stub.h. + + * tao/ORB_Core.cpp: + * tao/ORB_Core.h: + * tao/ORB_Core.i: ObjectKey_Table would now be a member of the + ORB_Core class, initialized during the init () call and + destroyed during TAO_ORB_Core::fini (). This class also provides + an accessor for accessing the ObjectKey_Table. + + * tao/Resource_Factory.cpp: + * tao/Resource_Factory.h: Added a virtual method + create_object_key_table_lock () that helps in creating the right + type of lock for the ObjectKey_Table. + + * tao/default_resource.cpp: + * tao/default_resource.h: Implementation for + create_object_key_table_lock (). + + Added an option -ORBObjectKeyTableLock that helps the user to + configure the type of lock used. + + * tao/Makefile.tao: Added the new files into the Makefile. + Sun May 11 10:37:56 2003 Nanbor Wang <nanbor@cs.wustl.edu> Checked in updates that sat in my workspace for a long time. diff --git a/TAO/tao/IIOP_Profile.cpp b/TAO/tao/IIOP_Profile.cpp index 8bd9333d8b1..62c8f740edf 100644 --- a/TAO/tao/IIOP_Profile.cpp +++ b/TAO/tao/IIOP_Profile.cpp @@ -198,7 +198,10 @@ TAO_IIOP_Profile::parse_string_i (const char *ior this->endpoint_.host_ = CORBA::string_dup (tmp_host); } - TAO::ObjectKey::decode_string_to_sequence (this->object_key_, okd + 1); + TAO::ObjectKey &ok = ACE_const_cast (TAO::ObjectKey&, + this->ref_object_key_->object_key ()); + TAO::ObjectKey::decode_string_to_sequence (ok, + okd + 1); } CORBA::Boolean @@ -212,7 +215,8 @@ TAO_IIOP_Profile::is_equivalent (const TAO_Profile *other_profile) ACE_dynamic_cast (const TAO_IIOP_Profile *, other_profile); - if (!(this->object_key_ == op->object_key_ + if (!(this->ref_object_key_->object_key () == + op->ref_object_key_->object_key () && this->version_ == op->version_ && this->count_ == op->count_)) return 0; @@ -248,10 +252,13 @@ TAO_IIOP_Profile::hash (CORBA::ULong max hashval += this->version_.minor; hashval += this->tag (); - if (this->object_key_.length () >= 4) + const TAO::ObjectKey &ok = + this->ref_object_key_->object_key (); + + if (ok.length () >= 4) { - hashval += this->object_key_ [1]; - hashval += this->object_key_ [3]; + hashval += ok[1]; + hashval += ok[3]; } return hashval % max; @@ -283,7 +290,7 @@ TAO_IIOP_Profile::to_string (ACE_ENV_SINGLE_ARG_DECL_NOT_USED) { CORBA::String_var key; TAO::ObjectKey::encode_sequence_to_string (key.inout(), - this->object_key_); + this->ref_object_key_->object_key ()); size_t buflen = (8 /* "corbaloc" */ + 1 /* colon separator */ + @@ -338,7 +345,14 @@ TAO_IIOP_Profile::create_profile_body (TAO_OutputCDR &encap) const encap.write_ushort (this->endpoint_.port ()); // OCTET SEQUENCE for object key - encap << this->object_key_; + if (this->ref_object_key_) + encap << this->ref_object_key_->object_key (); + else + { + ACE_ERROR ((LM_ERROR, + "(%P|%t) TAO - IIOP_Profile::create_profile_body ", + "no object key marshalled \n")); + } if (this->version_.major > 1 || this->version_.minor > 0) diff --git a/TAO/tao/IIOP_Transport.cpp b/TAO/tao/IIOP_Transport.cpp index 95a3d7b4c6a..69a1f2acab9 100644 --- a/TAO/tao/IIOP_Transport.cpp +++ b/TAO/tao/IIOP_Transport.cpp @@ -10,7 +10,6 @@ #include "Transport_Mux_Strategy.h" #include "Wait_Strategy.h" #include "Sync_Strategies.h" -#include "Stub.h" #include "ORB_Core.h" #include "debug.h" #include "GIOP_Message_Base.h" diff --git a/TAO/tao/Makefile.tao b/TAO/tao/Makefile.tao index 006c88d3185..d364774a214 100644 --- a/TAO/tao/Makefile.tao +++ b/TAO/tao/Makefile.tao @@ -296,7 +296,9 @@ ORB_CORE_FILES = \ Default_Thread_Lane_Resources_Manager \ Default_Stub_Factory \ Request_Dispatcher \ - Valuetype_Adapter + Valuetype_Adapter \ + ObjectKey_Table \ + Refcounted_ObjectKey DYNAMIC_ANY_FILES = diff --git a/TAO/tao/ORB_Core.cpp b/TAO/tao/ORB_Core.cpp index b68e3484258..13a08daa3f9 100644 --- a/TAO/tao/ORB_Core.cpp +++ b/TAO/tao/ORB_Core.cpp @@ -142,14 +142,9 @@ TAO_ORB_Core::TAO_ORB_Core (const char *orbid) orb_params_ (), init_ref_map_ (TAO_DEFAULT_OBJECT_REF_TABLE_SIZE), object_ref_table_ (), + object_key_table_ (), orbid_ (ACE_OS::strdup (orbid ? orbid : "")), resource_factory_ (0), -#if 0 - /// @@todo:Need to go one day - message_block_dblock_allocator_ (0), - message_block_buffer_allocator_ (0), - message_block_msgblock_allocator_ (0), -#endif /*if 0*/ // server_id_ (0), client_factory_ (0), server_factory_ (0), @@ -923,6 +918,9 @@ TAO_ORB_Core::init (int &argc, char *argv[] ACE_ENV_ARG_DECL) ssf->open (this); + // Open the ObjectKey_Table + (void) this->object_key_table_.init (this); + // Obtain the timeout value for the thread-per-connection model this->thread_per_connection_use_timeout_ = ssf->thread_per_connection_timeout (this->thread_per_connection_timeout_); @@ -1123,20 +1121,8 @@ TAO_ORB_Core::fini (void) (void) TAO_Internal::close_services (); -#if 0 - // @@todo: Need to go someday! - if (this->message_block_dblock_allocator_) - this->message_block_dblock_allocator_->remove (); - delete this->message_block_dblock_allocator_; - - if (this-> message_block_buffer_allocator_) - this->message_block_buffer_allocator_->remove (); - delete this->message_block_buffer_allocator_; - - if (this->message_block_msgblock_allocator_) - this->message_block_msgblock_allocator_->remove (); - delete this->message_block_msgblock_allocator_; -#endif /*if 0*/ + // Destroy the object_key table + this->object_key_table_.destroy (); delete this; diff --git a/TAO/tao/ORB_Core.h b/TAO/tao/ORB_Core.h index 50db8476681..39fe569890d 100644 --- a/TAO/tao/ORB_Core.h +++ b/TAO/tao/ORB_Core.h @@ -35,6 +35,7 @@ #include "Fault_Tolerance_Service.h" #include "Cleanup_Func_Registry.h" #include "Object_Ref_Table.h" +#include "ObjectKey_Table.h" // Interceptor definitions. #include "PortableInterceptorC.h" @@ -922,6 +923,9 @@ public: /// the resolve_initial_references() mechanism. TAO_Object_Ref_Table &object_ref_table (void); + /// Acceessor to the table that stores the object_keys. + TAO::ObjectKey_Table &object_key_table (void); + /// Return the current request dispatcher strategy. TAO_Request_Dispatcher *request_dispatcher (void); @@ -1096,6 +1100,9 @@ protected: /// resolve_initial_references() mechanism. TAO_Object_Ref_Table object_ref_table_; + /// Table that stores the object key instead of caching one per-profile. + TAO::ObjectKey_Table object_key_table_; + /// The ORBid for this ORB. char *orbid_; diff --git a/TAO/tao/ORB_Core.i b/TAO/tao/ORB_Core.i index 0bc65fe7e2b..b5fc98a3ccd 100644 --- a/TAO/tao/ORB_Core.i +++ b/TAO/tao/ORB_Core.i @@ -50,6 +50,12 @@ TAO_ORB_Core::object_ref_table (void) return this->object_ref_table_; } +ACE_INLINE TAO::ObjectKey_Table & +TAO_ORB_Core::object_key_table (void) +{ + return this->object_key_table_; +} + ACE_INLINE TAO_Flushing_Strategy * TAO_ORB_Core::flushing_strategy (void) { diff --git a/TAO/tao/ObjectKey_Table.cpp b/TAO/tao/ObjectKey_Table.cpp new file mode 100644 index 00000000000..7013bc4e620 --- /dev/null +++ b/TAO/tao/ObjectKey_Table.cpp @@ -0,0 +1,169 @@ +//$Id$ +#include "ObjectKey_Table.h" +#include "ORB_Core.h" +#include "Refcounted_ObjectKey.h" + +ACE_RCSID(tao, + ObjectKey_Table, + "$Id$") + + +TAO::ObjectKey_Table::ObjectKey_Table (void) + : lock_ (0) + , table_ () +{ + +} + +TAO::ObjectKey_Table::~ObjectKey_Table (void) +{ + this->table_.close (); + delete this->lock_; +} + +int +TAO::ObjectKey_Table::init (TAO_ORB_Core *oc) +{ + /// Create the lock that is needed for internal usage. + this->lock_ = + oc->resource_factory ()->create_object_key_table_lock (); + + return 0; +} + +int +TAO::ObjectKey_Table::bind (const TAO::ObjectKey &key, + TAO::Refcounted_ObjectKey *&key_new) + +{ + key_new = 0; + + // NOTE:Place for optimization. This is real expensive.. + CORBA::String_var str; + TAO::ObjectKey::encode_sequence_to_string (str.inout (), + key); + + // Hash values can be tricky, but even then thy are useful at + // times. + u_long hash_val = + ACE::hash_pjw (str.in ()); + + int retval = 0; + { + ACE_GUARD_RETURN (ACE_Lock, + ace_mon, + *this->lock_, + 0); + + // This is a tradeoff.. We could avoid this two stage process of + // using a find () and then a bind () , which would make things + // efficient. BUT we may have to do allocation upfront and delete if + // bind () returns with an entry. We take one of the routes that + // avoids allocation. + retval = this->table_.find (hash_val, + key_new); + + if (retval == -1) + return this->bind_i (hash_val, + key, + key_new); + + + // Do a sanity comparison check and increment the refcount. + // Place for optimization by removing the comparison. + if (key_new->object_key () == key) + { + (void) key_new->incr_refcount (); + } + else + { + // Do we bind it again. And if so, how? + // Need to thinkk.... + } + } + + return 0; +} + +int +TAO::ObjectKey_Table::unbind (TAO::Refcounted_ObjectKey *&key_new) + +{ + ACE_GUARD_RETURN (ACE_Lock, + ace_mon, + *this->lock_, + 0); + // If the refcount has dropped to 1, just go ahead and unbind it + // from the table. + if (key_new->decr_refcount () == 1) + return this->unbind_i (key_new); + + return 0; +} + +int +TAO::ObjectKey_Table::destroy (void) +{ + if (this->table_.current_size ()) + { + ACE_GUARD_RETURN (ACE_Lock, + ace_mon, + *this->lock_, + 0); + + TABLE::ITERATOR end_iter = this->table_.end (); + + for (TABLE::ITERATOR start = this->table_.begin (); + start != end_iter; + ++start) + { + TABLE::ENTRY &ent = (*start); + + (void) ent.item ()->decr_refcount (); + + this->table_.unbind (&ent); + } + } + + return 0; +} + +int +TAO::ObjectKey_Table::bind_i (u_long hash_val, + const TAO::ObjectKey &key, + TAO::Refcounted_ObjectKey *&key_new) +{ + ACE_NEW_RETURN (key_new, + TAO::Refcounted_ObjectKey (key), + -1); + + int retval = this->table_.bind (hash_val, + key_new); + + if (retval != -1) + key_new->incr_refcount (); + else + key_new->decr_refcount (); + + return retval; +} + +int +TAO::ObjectKey_Table::unbind_i (TAO::Refcounted_ObjectKey *&key_new) +{ + // NOTE:Place for optimization. This is real expensive.. + CORBA::String_var str; + TAO::ObjectKey::encode_sequence_to_string (str.inout (), + key_new->object_key ()); + + u_long hash_val = + ACE::hash_pjw (str.in ()); + + (void) this->table_.unbind (hash_val, + key_new); + + // Remove our refcount on the ObjectKey + (void) key_new->decr_refcount (); + + return 0; +} diff --git a/TAO/tao/ObjectKey_Table.h b/TAO/tao/ObjectKey_Table.h new file mode 100644 index 00000000000..52ded9b5294 --- /dev/null +++ b/TAO/tao/ObjectKey_Table.h @@ -0,0 +1,125 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file ObjectKey_Table.h + * + * $Id$ + * + * @author Balachandran Natarajan <bala@dre.vanderbilt.edu> + */ +//============================================================================= +#ifndef TAO_OBJECTKEY_TABLE_H +#define TAO_OBJECTKEY_TABLE_H +#include "ace/pre.h" +#include "ace/RB_Tree.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "tao/TAO_Export.h" + + +// Forward declarations +class TAO_ORB_Core; + + +namespace TAO +{ + + // Forward declarations within the namespace.. + + class ObjectKey; + class Refcounted_ObjectKey; + + /** + * @class ObjectKey_Table + * + * @brief Table that maintains the set of ObjectKey's seen by the + * ORB. + * + * The ORB maintains one table for the whole ORB. ObjectKeys + * generated by the ORB or the ones seen by the ORB from remote + * ORB's are stored here. The ObjectKeys are stored through a + * wrapper which encapsulates the refcount on them. This class + * actually provides the synchronization mechanism for manipulating + * the reference counts on the object keys provided by the wrapper + * class. + * + * This class does not offer a find () call with a reason. The call + * to bind () will return a pointer which is expected to be cached + * by the client/caller and use the pointer in every invocation. + * + * @NOTE: This class uses the ACE_RB_Tree to maintain the table of + * ObjectKeys. The RB_Tree has good insertion and lookup + * properties. Its Iteration properties are not that good, but we + * dont need to do much iteration unless we are closing down the + * table. + * + * @NOTE: The reasons to use RB_Tree are its good dynamic + * properties. We should try to strategize the class to use either a + * Hash_Map or a RB_Tree based on some runtime option. For that we + * need an adapter class in ACE, like an ACE_Lock_Adapter class. We + * will do that if our instrumentation shows the need for it. + * + */ + class TAO_Export ObjectKey_Table + { + public: + /// Default Constructor and destructor.. + ObjectKey_Table (void); + + ~ObjectKey_Table (void); + + /// Initialize method that sets up the underlying lock and other + /// related stuff. + int init (TAO_ORB_Core *orb); + + /// Iterates and unbinds the contents of the table. + int destroy (void); + + /// Bind the ObjectKey in the table. + /** + * Bind an ObjectKey in the table and return a pointer to the + * Refcounted_ObjectKey which the client can use. If the ObjectKey + * is already available in the table, this operation just + * increments the refcount on the ObjectKey. If the ObjectKey is + * new it is bounded to the table. Returns a 0 on success and a -1 + * on failure. + */ + int bind (const ObjectKey &key, + Refcounted_ObjectKey *&key_new); + + /// Unbind an ObjectKey from the table. + int unbind (TAO::Refcounted_ObjectKey *&key); + + protected: + /// Implementation for bind (). + int bind_i (u_long hash_val, + const ObjectKey &key, + Refcounted_ObjectKey *&key_new); + + /// Implementation for unbind (). + int unbind_i (Refcounted_ObjectKey *&key); + + private: + + // Some useful typedefs. + typedef unsigned long ExtId; + + typedef ACE_RB_Tree<ExtId, + TAO::Refcounted_ObjectKey *, + ACE_Less_Than <ExtId>, + ACE_Null_Mutex> TABLE; + + /// Lock for the table. + ACE_Lock *lock_; + + /// Table that contains the data + TABLE table_; + }; +} + +#include "ace/post.h" +#endif /*TAO_OBJECT_KEY_TABLE_H*/ diff --git a/TAO/tao/Profile.cpp b/TAO/tao/Profile.cpp index 341efa8f02d..69ab21cdd43 100644 --- a/TAO/tao/Profile.cpp +++ b/TAO/tao/Profile.cpp @@ -6,6 +6,8 @@ #include "Stub.h" #include "debug.h" #include "target_specification.h" +#include "Object_KeyC.h" +#include "ORB_Core.h" #include "ace/CDR_Base.h" #if !defined (__ACE_INLINE__) @@ -27,12 +29,14 @@ TAO_Profile::TAO_Profile (CORBA::ULong tag, , policy_list_ (0) , addressing_mode_ (0) , tagged_profile_ (0) - , object_key_ (obj_key) + , ref_object_key_ (0) , tag_ (tag) , orb_core_ (orb_core) , forward_to_ (0) , refcount_ (1) { + (void) this->orb_core_->object_key_table ().bind (obj_key, + this->ref_object_key_); } TAO_Profile::TAO_Profile (CORBA::ULong tag, @@ -44,7 +48,7 @@ TAO_Profile::TAO_Profile (CORBA::ULong tag, , policy_list_ (0) , addressing_mode_ (0) , tagged_profile_ (0) - , object_key_ () + , ref_object_key_ (0) , tag_ (tag) , orb_core_ (orb_core) , forward_to_ (0) @@ -56,6 +60,8 @@ TAO_Profile::~TAO_Profile (void) { if (this->tagged_profile_) delete this->tagged_profile_; + + this->orb_core_->object_key_table ().unbind (this->ref_object_key_); } CORBA::ULong @@ -107,10 +113,12 @@ TAO_Profile::_key (void) const { TAO::ObjectKey *key = 0; - ACE_NEW_RETURN (key, - TAO::ObjectKey (this->object_key_), - 0); - + if (this->ref_object_key_) + { + ACE_NEW_RETURN (key, + TAO::ObjectKey (this->ref_object_key_->object_key ()), + 0); + } return key; } @@ -166,8 +174,30 @@ TAO_Profile::decode (TAO_InputCDR& cdr) if (this->decode_profile (cdr) < 0) return -1; + // @@NOTE: This place *may* need strategizing. Here are the + // issues. Placing the ObjectKey in the table adds an allocation and + // a lock while decoding. This is bad for some cases especially if + // the application is marshalling object references across to the + // server end. But the server could use "lazy" evaluation and avoid + // this during marshalling. + // + // The only place this will get important is when a thead tries to + // use the object reference to create a CORBA object to make an + // invocation. Since creation of a CORBA object itself is expensive, + // it looks like we may not need to worry much. + // + // Remember strategizing needs reconciliation of forces imposed + // by runtime memory growth. Doing a random strategization would + // destroy the wins in runtime memory growth got by using this + // table scheme. + TAO::ObjectKey ok; + // ... and object key. - if ((cdr >> this->object_key_) == 0) + if ((cdr >> ok) == 0) + return -1; + + if (this->orb_core ()->object_key_table ().bind (ok, + this->ref_object_key_) == -1) return -1; // Tagged Components *only* exist after version 1.0! diff --git a/TAO/tao/Profile.h b/TAO/tao/Profile.h index c5cce5ef180..f512f55b8ef 100644 --- a/TAO/tao/Profile.h +++ b/TAO/tao/Profile.h @@ -20,22 +20,26 @@ #endif /* ACE_LACKS_PRAGMA_ONCE */ #include "tao/GIOP_Message_Version.h" -#include "tao/Object_KeyC.h" - - #include "ace/Synch.h" +#include "tao/Refcounted_ObjectKey.h" class TAO_MProfile; class TAO_Stub; class TAO_Endpoint; class TAO_ORB_Core; + /// Forward declaration of PolicyList namespace CORBA { class PolicyList; } +namespace TAO +{ + class Refcounted_ObjectKey; +} + /** * @class TAO_Profile * @@ -309,7 +313,7 @@ protected: IOP::TaggedProfile *tagged_profile_; /// object_key associated with this profile. - TAO::ObjectKey object_key_; + TAO::Refcounted_ObjectKey *ref_object_key_; private: /// IOP protocol tag. diff --git a/TAO/tao/Profile.i b/TAO/tao/Profile.i index af9ff0b4b14..dde1611c1da 100644 --- a/TAO/tao/Profile.i +++ b/TAO/tao/Profile.i @@ -58,5 +58,5 @@ TAO_Profile::addressing_mode (void) const ACE_INLINE const TAO::ObjectKey & TAO_Profile::object_key (void) const { - return this->object_key_; + return this->ref_object_key_->object_key (); } diff --git a/TAO/tao/Refcounted_ObjectKey.cpp b/TAO/tao/Refcounted_ObjectKey.cpp new file mode 100644 index 00000000000..b2cd277b7e0 --- /dev/null +++ b/TAO/tao/Refcounted_ObjectKey.cpp @@ -0,0 +1,23 @@ +//$Id$ +#include "Refcounted_ObjectKey.h" + + +#if !defined (__ACE_INLINE__) +#include "Refcounted_ObjectKey.inl" +#endif /* defined INLINE */ + +ACE_RCSID(tao, + Refcounted_ObjectKey, + "$Id$") + + +TAO::Refcounted_ObjectKey::Refcounted_ObjectKey (const TAO::ObjectKey &key) + : object_key_ (key) + , ref_count_ (1) +{ +} + + +TAO::Refcounted_ObjectKey::~Refcounted_ObjectKey (void) +{ +} diff --git a/TAO/tao/Refcounted_ObjectKey.h b/TAO/tao/Refcounted_ObjectKey.h new file mode 100644 index 00000000000..deaae1841ba --- /dev/null +++ b/TAO/tao/Refcounted_ObjectKey.h @@ -0,0 +1,68 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file Refcounted_ObjectKey.h + * + * $Id$ + * + * @author Balachandran Natarajan <bala@dre.vanderbilt.edu> + */ +//============================================================================= +#ifndef TAO_REFCOUNTED_OBJECTKEY_H +#define TAO_REFCOUNTED_OBJECTKEY_H +#include "ace/pre.h" + +#include "tao/Object_KeyC.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +namespace TAO +{ + /** + * @class Refcounted_ObjectKey + * + * @brief A wrapper class that ties together a refcount to an + * ObjectKey. + * + * The refounts in this class is manipulated within the context of + * the lock in the TAO::ObjectKey_Table. Manipulating the refcounts + * from anywhere else is strictly forbidden. + */ + class TAO_Export Refcounted_ObjectKey + { + public: + /// Constructor + Refcounted_ObjectKey (const ObjectKey &ref); + + /// Accessor for the underlying ObjectKey. + const ObjectKey &object_key (void) const; + + protected: + friend class ObjectKey_Table; + + /// Protected destructor + ~Refcounted_ObjectKey (void); + + /// Methods for incrementing and decrementing refcounts. + long incr_refcount (void); + long decr_refcount (void); + + private: + /// The object key + ObjectKey object_key_; + + /// The refcount on the object key.. + long ref_count_; + }; + +} + +#if defined (__ACE_INLINE__) +#include "Refcounted_ObjectKey.inl" +#endif /* defined INLINE */ + +#include "ace/post.h" +#endif /*TAO_REFCOUNTED_OBJECTKEY_H*/ diff --git a/TAO/tao/Refcounted_ObjectKey.inl b/TAO/tao/Refcounted_ObjectKey.inl new file mode 100644 index 00000000000..eccd955c4bb --- /dev/null +++ b/TAO/tao/Refcounted_ObjectKey.inl @@ -0,0 +1,26 @@ +// -*- C++ -*- +// $Id$ +ACE_INLINE long +TAO::Refcounted_ObjectKey::incr_refcount (void) +{ + return ++this->ref_count_; +} + +ACE_INLINE long +TAO::Refcounted_ObjectKey::decr_refcount (void) +{ + if (--this->ref_count_ > 0) + return this->ref_count_; + + ACE_ASSERT (this->ref_count_ == 0); + + delete this; + + return 0; +} + +ACE_INLINE const TAO::ObjectKey & +TAO::Refcounted_ObjectKey::object_key (void) const +{ + return this->object_key_; +} diff --git a/TAO/tao/Resource_Factory.cpp b/TAO/tao/Resource_Factory.cpp index 44063c904a0..86daf405582 100644 --- a/TAO/tao/Resource_Factory.cpp +++ b/TAO/tao/Resource_Factory.cpp @@ -195,6 +195,12 @@ TAO_Resource_Factory::locked_transport_cache (void) } ACE_Lock * +TAO_Resource_Factory::create_object_key_table_lock (void) +{ + return 0; +} + +ACE_Lock * TAO_Resource_Factory::create_corba_object_lock (void) { return 0; diff --git a/TAO/tao/Resource_Factory.h b/TAO/tao/Resource_Factory.h index b21e627a30c..46a2c30a67b 100644 --- a/TAO/tao/Resource_Factory.h +++ b/TAO/tao/Resource_Factory.h @@ -202,6 +202,9 @@ public: /// transport cache needs to be locked else return 0 virtual int locked_transport_cache (void); + /// Creates a lock needed for the table that stores the object keys. + virtual ACE_Lock *create_object_key_table_lock (void); + /// Creates the lock for the CORBA Object virtual ACE_Lock *create_corba_object_lock (void); diff --git a/TAO/tao/Strategies/DIOP_Profile.cpp b/TAO/tao/Strategies/DIOP_Profile.cpp index e99db319aa7..73cb6167905 100644 --- a/TAO/tao/Strategies/DIOP_Profile.cpp +++ b/TAO/tao/Strategies/DIOP_Profile.cpp @@ -208,7 +208,10 @@ TAO_DIOP_Profile::parse_string_i (const char *ior this->endpoint_.host_ = CORBA::string_dup (tmp_host); } - TAO::ObjectKey::decode_string_to_sequence (this->object_key_, okd + 1); + TAO::ObjectKey &ok = ACE_const_cast (TAO::ObjectKey&, + this->ref_object_key_->object_key ()); + TAO::ObjectKey::decode_string_to_sequence (ok, + okd + 1); } CORBA::Boolean @@ -222,7 +225,8 @@ TAO_DIOP_Profile::is_equivalent (const TAO_Profile *other_profile) ACE_dynamic_cast (const TAO_DIOP_Profile *, other_profile); - if (!(this->object_key_ == op->object_key_ + if (!(this->ref_object_key_->object_key () == + op->ref_object_key_->object_key () && this->version_ == op->version_ && this->count_ == op->count_)) return 0; @@ -258,10 +262,13 @@ TAO_DIOP_Profile::hash (CORBA::ULong max hashval += this->version_.minor; hashval += this->tag (); - if (this->object_key_.length () >= 4) + const TAO::ObjectKey &ok = + this->ref_object_key_->object_key (); + + if (ok.length () >= 4) { - hashval += this->object_key_ [1]; - hashval += this->object_key_ [3]; + hashval += ok[1]; + hashval += ok[3]; } return hashval % max; @@ -293,7 +300,7 @@ TAO_DIOP_Profile::to_string (ACE_ENV_SINGLE_ARG_DECL_NOT_USED) { CORBA::String_var key; TAO::ObjectKey::encode_sequence_to_string (key.inout(), - this->object_key_); + this->ref_object_key_->object_key ()); size_t buflen = (8 /* "corbaloc" */ + 1 /* colon separator */ + @@ -348,7 +355,14 @@ TAO_DIOP_Profile::create_profile_body (TAO_OutputCDR &encap) const encap.write_ushort (this->endpoint_.port ()); // OCTET SEQUENCE for object key - encap << this->object_key_; + if (this->ref_object_key_) + encap << this->ref_object_key_->object_key (); + else + { + ACE_ERROR ((LM_ERROR, + "(%P|%t) TAO - UIOP_Profile::create_profile_body ", + "no object key marshalled \n")); + } if (this->version_.major > 1 || this->version_.minor > 0) diff --git a/TAO/tao/Strategies/SHMIOP_Profile.cpp b/TAO/tao/Strategies/SHMIOP_Profile.cpp index fb9b5691ee7..6202344b417 100644 --- a/TAO/tao/Strategies/SHMIOP_Profile.cpp +++ b/TAO/tao/Strategies/SHMIOP_Profile.cpp @@ -236,7 +236,11 @@ TAO_SHMIOP_Profile::parse_string_i (const char *string start = ++okd; // increment past the object key separator - TAO::ObjectKey::decode_string_to_sequence (this->object_key_, start); + TAO::ObjectKey &ok = ACE_const_cast (TAO::ObjectKey&, + this->ref_object_key_->object_key ()); + + TAO::ObjectKey::decode_string_to_sequence (ok, + start); } CORBA::Boolean @@ -249,7 +253,8 @@ TAO_SHMIOP_Profile::is_equivalent (const TAO_Profile *other_profile) const TAO_SHMIOP_Profile *op = ACE_dynamic_cast (const TAO_SHMIOP_Profile *, other_profile); - if (!(this->object_key_ == op->object_key_ + if (!(this->ref_object_key_->object_key () == + op->ref_object_key_->object_key () && this->version_ == op->version_ && this->count_ == op->count_)) return 0; @@ -285,10 +290,13 @@ TAO_SHMIOP_Profile::hash (CORBA::ULong max hashval += this->version_.minor; hashval += this->tag (); - if (this->object_key_.length () >= 4) + const TAO::ObjectKey &ok = + this->ref_object_key_->object_key (); + + if (ok.length () >= 4) { - hashval += this->object_key_ [1]; - hashval += this->object_key_ [3]; + hashval += ok[1]; + hashval += ok[3]; } return hashval % max; @@ -308,7 +316,7 @@ TAO_SHMIOP_Profile::to_string (ACE_ENV_SINGLE_ARG_DECL_NOT_USED) { CORBA::String_var key; TAO::ObjectKey::encode_sequence_to_string (key.inout(), - this->object_key_); + this->ref_object_key_->object_key ()); size_t buflen = (8 /* corbaloc */ + 1 /* colon separator */ + @@ -362,7 +370,14 @@ TAO_SHMIOP_Profile::create_profile_body (TAO_OutputCDR &encap) const encap.write_ushort (this->endpoint_.port ()); // OCTET SEQUENCE for object key - encap << this->object_key_; + if (this->ref_object_key_) + encap << this->ref_object_key_->object_key (); + else + { + ACE_ERROR ((LM_ERROR, + "(%P|%t) TAO - UIOP_Profile::create_profile_body ", + "no object key marshalled \n")); + } if (this->version_.major > 1 || this->version_.minor > 0) diff --git a/TAO/tao/Strategies/UIOP_Profile.cpp b/TAO/tao/Strategies/UIOP_Profile.cpp index 8f8c8dacbdb..1613ac9e204 100644 --- a/TAO/tao/Strategies/UIOP_Profile.cpp +++ b/TAO/tao/Strategies/UIOP_Profile.cpp @@ -133,7 +133,10 @@ TAO_UIOP_Profile::parse_string_i (const char *string start = ++cp; // increment past the object key separator - TAO::ObjectKey::decode_string_to_sequence (this->object_key_, start); + TAO::ObjectKey &ok = ACE_const_cast (TAO::ObjectKey&, + this->ref_object_key_->object_key ()); + TAO::ObjectKey::decode_string_to_sequence (ok, + start); } CORBA::Boolean @@ -146,7 +149,8 @@ TAO_UIOP_Profile::is_equivalent (const TAO_Profile *other_profile) const TAO_UIOP_Profile *op = ACE_dynamic_cast (const TAO_UIOP_Profile *, other_profile); - if (!(this->object_key_ == op->object_key_ + if (!(this->ref_object_key_->object_key () == + op->ref_object_key_->object_key () && this->version_ == op->version_ && this->count_ == op->count_)) return 0; @@ -182,10 +186,13 @@ TAO_UIOP_Profile::hash (CORBA::ULong max hashval += this->version_.minor; hashval += this->tag (); - if (this->object_key_.length () >= 4) + const TAO::ObjectKey &ok = + this->ref_object_key_->object_key (); + + if (ok.length () >= 4) { - hashval += this->object_key_ [1]; - hashval += this->object_key_ [3]; + hashval += ok[1]; + hashval += ok[3]; } return hashval % max; @@ -206,7 +213,7 @@ TAO_UIOP_Profile::to_string (ACE_ENV_SINGLE_ARG_DECL_NOT_USED) { CORBA::String_var key; TAO::ObjectKey::encode_sequence_to_string (key.inout(), - this->object_key_); + this->ref_object_key_->object_key ()); u_int buflen = (8 /* "corbaloc" */ + 1 /* colon separator */ + @@ -289,7 +296,14 @@ TAO_UIOP_Profile::create_profile_body (TAO_OutputCDR &encap) const encap.write_string (this->endpoint_.rendezvous_point ()); // OCTET SEQUENCE for object key - encap << this->object_key_; + if (this->ref_object_key_) + encap << this->ref_object_key_->object_key (); + else + { + ACE_ERROR ((LM_ERROR, + "(%P|%t) TAO - UIOP_Profile::create_profile_body ", + "no object key marshalled \n")); + } if (this->version_.major > 1 || this->version_.minor > 0) diff --git a/TAO/tao/default_resource.cpp b/TAO/tao/default_resource.cpp index 430008e9902..8c759dac768 100644 --- a/TAO/tao/default_resource.cpp +++ b/TAO/tao/default_resource.cpp @@ -49,6 +49,7 @@ TAO_Default_Resource_Factory::TAO_Default_Resource_Factory (void) , options_processed_ (0) , factory_disabled_ (0) , cached_connection_lock_type_ (TAO_THREAD_LOCK) + , object_key_table_lock_type_ (TAO_THREAD_LOCK) , corba_object_lock_type_ (TAO_THREAD_LOCK) , flushing_strategy_type_ (TAO_LEADER_FOLLOWER_FLUSHING) , codeset_manager_ (0) @@ -373,6 +374,29 @@ TAO_Default_Resource_Factory::init (int argc, ACE_TCHAR *argv[]) } } else if (ACE_OS::strcasecmp (argv[curarg], + ACE_LIB_TEXT("-ORBObjectKeyTableLock")) == 0) + { + curarg++; + if (curarg < argc) + { + ACE_TCHAR* name = argv[curarg]; + + if (ACE_OS::strcasecmp (name, + ACE_LIB_TEXT("thread")) == 0) + this->object_key_table_lock_type_ = TAO_THREAD_LOCK; + else if (ACE_OS::strcasecmp (name, + ACE_LIB_TEXT("null")) == 0) + { + // @@ Bug 940 :This is a sort of hack now. We need to put + // this in a common place once we get the common + // switch that is documented in bug 940... + this->object_key_table_lock_type_ = TAO_NULL_LOCK; + } + else + this->report_option_value_error (ACE_LIB_TEXT("-ORBObjectKeyTableLock"), name); + } + } + else if (ACE_OS::strcasecmp (argv[curarg], ACE_LIB_TEXT("-ORBCorbaObjectLock")) == 0) { curarg++; @@ -874,6 +898,23 @@ TAO_Default_Resource_Factory::locked_transport_cache (void) ACE_Lock * +TAO_Default_Resource_Factory::create_object_key_table_lock (void) +{ + ACE_Lock *the_lock = 0; + + if (this->object_key_table_lock_type_ == TAO_NULL_LOCK) + ACE_NEW_RETURN (the_lock, + ACE_Lock_Adapter<ACE_SYNCH_NULL_MUTEX>, + 0); + else + ACE_NEW_RETURN (the_lock, + ACE_Lock_Adapter<TAO_SYNCH_MUTEX>, + 0); + + return the_lock; +} + +ACE_Lock * TAO_Default_Resource_Factory::create_corba_object_lock (void) { ACE_Lock *the_lock = 0; diff --git a/TAO/tao/default_resource.h b/TAO/tao/default_resource.h index 44c2811e2bd..a00ebe36700 100644 --- a/TAO/tao/default_resource.h +++ b/TAO/tao/default_resource.h @@ -126,6 +126,7 @@ public: virtual int purge_percentage (void) const; virtual int max_muxed_connections (void) const; virtual ACE_Lock *create_cached_connection_lock (void); + virtual ACE_Lock *create_object_key_table_lock (void); virtual ACE_Lock *create_corba_object_lock (void); virtual int locked_transport_cache (void); virtual TAO_Flushing_Strategy *create_flushing_strategy (void); @@ -220,6 +221,9 @@ private: Lock_Type cached_connection_lock_type_; /// Type of lock used by the corba object. + Lock_Type object_key_table_lock_type_; + + /// Type of lock used by the corba object. Lock_Type corba_object_lock_type_; enum Flushing_Strategy_Type |