00001 // -*- C++ -*- 00002 00003 //============================================================================= 00004 /** 00005 * @file Transport_Cache_Manager.h 00006 * 00007 * $Id: Transport_Cache_Manager.h 79388 2007-08-17 16:05:00Z wilsond $ 00008 * 00009 * @author Balachandran Natarajan <bala@cs.wustl.edu> 00010 */ 00011 //============================================================================= 00012 00013 #ifndef TAO_CONNECTION_CACHE_MANAGER_H 00014 #define TAO_CONNECTION_CACHE_MANAGER_H 00015 00016 #include /**/ "ace/pre.h" 00017 #include "ace/Null_Mutex.h" 00018 00019 #if !defined (ACE_LACKS_PRAGMA_ONCE) 00020 #define ACE_LACKS_PRAGMA_ONCE 00021 #endif /* ACE_LACKS_PRAGMA_ONCE */ 00022 00023 #include "ace/Hash_Map_Manager_T.h" 00024 00025 #include "tao/Cache_Entries.h" 00026 #include "tao/orbconf.h" 00027 00028 ACE_BEGIN_VERSIONED_NAMESPACE_DECL 00029 class ACE_Handle_Set; 00030 template <class T> class ACE_Unbounded_Set; 00031 template <class T> class ACE_Unbounded_Set_Iterator; 00032 ACE_END_VERSIONED_NAMESPACE_DECL 00033 00034 TAO_BEGIN_VERSIONED_NAMESPACE_DECL 00035 00036 class TAO_Connection_Handler; 00037 class TAO_ORB_Core; 00038 class TAO_Resource_Factory; 00039 class TAO_Connection_Purging_Strategy; 00040 00041 template <class ACE_COND_MUTEX> class TAO_Condition; 00042 00043 namespace TAO 00044 { 00045 typedef ACE_Unbounded_Set<TAO_Connection_Handler*> Connection_Handler_Set; 00046 /** 00047 * @class Transport_Cache_Manager 00048 * 00049 * @brief The Transport Cache Manager for TAO 00050 * 00051 * This class provides interfaces associating a TAO_Cache_ExtId 00052 * & TAO_Cache_IntId. This class is wrapper around the 00053 * ACE_Hash_Map_Manager class which is used as a container to Cache 00054 * the connections. This class protects the entries with a lock. The 00055 * map is updated only by holding the lock. The more compelling reason 00056 * to have the lock in this class and not in the Hash_Map is that, we 00057 * do quite a bit of work in this class for which we need a lock. 00058 * 00059 */ 00060 class TAO_Export Transport_Cache_Manager 00061 { 00062 public: 00063 // Some useful typedef's 00064 typedef ACE_Hash_Map_Manager_Ex <Cache_ExtId, 00065 Cache_IntId, 00066 ACE_Hash<Cache_ExtId>, 00067 ACE_Equal_To<Cache_ExtId>, 00068 ACE_Null_Mutex> 00069 HASH_MAP; 00070 00071 typedef HASH_MAP::iterator HASH_MAP_ITER; 00072 00073 typedef ACE_Hash_Map_Entry <Cache_ExtId, 00074 Cache_IntId> 00075 HASH_MAP_ENTRY; 00076 00077 typedef TAO_Condition<TAO_SYNCH_MUTEX> CONDITION; 00078 00079 // == Public methods 00080 /// Constructor 00081 Transport_Cache_Manager (TAO_ORB_Core &orb_core); 00082 00083 /// Destructor 00084 ~Transport_Cache_Manager (void); 00085 00086 /// Add the transport to the cache. 00087 /** 00088 * The transport has the property definition based on which caching 00089 * can be done. This method marks the transport 00090 * <CODE>ACE_RECYCLABLE_BUSY </CODE> which helps the threads 00091 * opening up connections to use the transport immediately. 00092 */ 00093 int cache_transport (TAO_Transport_Descriptor_Interface *prop, 00094 TAO_Transport *transport); 00095 00096 /// Similar to the one above, but the transport is left in <CODE> 00097 /// ENTRY_IDLE_AND_PURGABLE</CODE> state. 00098 int cache_idle_transport (TAO_Transport_Descriptor_Interface *prop, 00099 TAO_Transport *transport); 00100 00101 /// Check the Transport Cache to check whether the connection exists 00102 /// in the Cache and return the connection 00103 int find_transport (TAO_Transport_Descriptor_Interface *prop, 00104 TAO_Transport *&transport); 00105 00106 /// Remove entries from the cache depending upon the strategy. 00107 int purge (void); 00108 00109 /// Purge the entry from the Cache Map 00110 int purge_entry (HASH_MAP_ENTRY *&); 00111 00112 /// Mark the entry as invalid for use but keep it in cache. 00113 void mark_invalid (HASH_MAP_ENTRY *&); 00114 00115 /// Make the entry idle and ready for use. 00116 int make_idle (HASH_MAP_ENTRY *&entry); 00117 00118 /// Mark the entry as touched. This call updates the purging 00119 /// strategy policy information. 00120 int update_entry (HASH_MAP_ENTRY *&entry); 00121 00122 /// Close the underlying hash map manager and return any handlers 00123 /// still registered 00124 int close (Connection_Handler_Set &handlers); 00125 00126 /// Return a set of connection handlers that belong to transports 00127 /// that have a RW wait strategy. 00128 /** 00129 * This call is used for a specific use case by the ORB_Core 00130 * during shutdown. The only way the ORB can wake up threads 00131 * waiting on these sockstes for replies is to iterate over 00132 * these blockable transports and close the socket 00133 * handles. Without these the threads will continue to wait there 00134 * for ever. 00135 */ 00136 bool blockable_client_transports (Connection_Handler_Set &handlers); 00137 00138 /// Return the current size of the cache. 00139 size_t current_size (void) const; 00140 00141 /// Return the total size of the cache. 00142 size_t total_size (void) const; 00143 00144 /// Return the underlying cache map 00145 HASH_MAP &map (void); 00146 00147 private: 00148 /// Associate @a ext_id with @a int_id. Grabs the lock and calls the 00149 /// implementation function bind_i. 00150 int bind (Cache_ExtId &ext_id, 00151 Cache_IntId &int_id); 00152 00153 /// Lookup entry<key,value> in the cache. Grabs the lock and calls the 00154 /// implementation function find_i. 00155 int find (const Cache_ExtId &key, 00156 Cache_IntId &value); 00157 00158 /** 00159 * Non-Locking version and actual implementation of bind () 00160 * call. Calls bind on the Hash_Map_Manager that it holds. If the 00161 * bind succeeds, it adds the Hash_Map_Entry in to the 00162 * Transport for its reference. If the bind fails because 00163 * of an exiting entry, this method calls the get_last_index_bind 00164 * (). 00165 */ 00166 int bind_i (Cache_ExtId &ext_id, 00167 Cache_IntId &int_id); 00168 00169 /** 00170 * Non-locking version and actual implementation of find () 00171 * call. This calls the find () on the underlying 00172 * Hash_Map_Manager. If the find succeeds, it calls the 00173 * get_idle_transport (). 00174 */ 00175 int find_i (const Cache_ExtId &key, 00176 Cache_IntId &value); 00177 00178 /// Non-locking version and actual implementation of make_idle (). 00179 int make_idle_i (HASH_MAP_ENTRY *&entry); 00180 00181 /// Non-locking version and actual implementation of close () 00182 int close_i (Connection_Handler_Set &handlers); 00183 00184 /// Purge the entry from the Cache Map 00185 int purge_entry_i (HASH_MAP_ENTRY *&entry); 00186 00187 /// Mark the entry as invalid for use but keep it in cache. 00188 void mark_invalid_i (HASH_MAP_ENTRY *&); 00189 00190 private: 00191 /** 00192 * This is called by the bind () call when a bind fails with a 00193 * available entry. When a new connection is created in TAO with an 00194 * already existing endpoint, in addition to an exisitng one, we 00195 * mark the connections with an index. This method, finds out the 00196 * last highest index and binds the entry with an index = (last 00197 * highest index + 1). 00198 */ 00199 int get_last_index_bind (Cache_ExtId &key, 00200 Cache_IntId &val, 00201 HASH_MAP_ENTRY *&entry); 00202 00203 /** 00204 * Tries to find if the <int_id_> in entry is idle for use. If it is 00205 * idle it is immediately markes as busy and returns a value of 00206 * 1, else it returns a value of 0 00207 */ 00208 bool is_entry_idle (HASH_MAP_ENTRY *&entry); 00209 00210 #if !defined(ACE_LACKS_QSORT) 00211 /// Used by qsort 00212 static int cpscmp(const void* a, const void* b); 00213 #endif 00214 00215 typedef HASH_MAP_ENTRY** DESCRIPTOR_SET; 00216 00217 /// Sort the list of entries 00218 void sort_set (DESCRIPTOR_SET& entries, int size); 00219 00220 /// Fill sorted_set in with the TAO_Transport_Descriptor_Interface's in 00221 /// a sorted order. 00222 int fill_set_i (DESCRIPTOR_SET& sorted_set); 00223 00224 /// Wait for connections if we have reached the limit on the number 00225 /// of muxed connections. If not (ie. if we dont use a muxed 00226 /// connection or if we have not reached the limit) this just 00227 /// behaves as a no-op. <extid> has all the information about the 00228 /// connection that is being searched. 00229 int wait_for_connection (Cache_ExtId &extid); 00230 00231 /// Is the wakeup useful todo some work? 00232 int is_wakeup_useful (Cache_ExtId &extid); 00233 00234 /// Non-locking version of blockable_client_transports (). 00235 bool blockable_client_transports_i (Connection_Handler_Set &handlers); 00236 00237 private: 00238 /// The percentage of the cache to purge at one time 00239 int percent_; 00240 00241 /// The underlying connection purging strategy 00242 TAO_Connection_Purging_Strategy *purging_strategy_; 00243 00244 /// The hash map that has the connections 00245 HASH_MAP cache_map_; 00246 00247 /// The condition variable 00248 CONDITION *condition_; 00249 00250 /// The lock that is used by the cache map 00251 ACE_Lock *cache_lock_; 00252 00253 /// Number of allowed muxed connections 00254 CORBA::ULong muxed_number_; 00255 00256 /// Number of threads waiting for connections 00257 int no_waiting_threads_; 00258 00259 /// This is for optimization purposes. In a situation where number 00260 /// of threads are waiting for connections, the last connection that 00261 /// is put back is cached here. This should prevent all th threads 00262 /// trying to search for their required entry. 00263 Cache_ExtId *last_entry_returned_; 00264 }; 00265 00266 } 00267 00268 TAO_END_VERSIONED_NAMESPACE_DECL 00269 00270 #if defined (__ACE_INLINE__) 00271 # include "tao/Transport_Cache_Manager.inl" 00272 #endif /* __ACE_INLINE__ */ 00273 00274 #include /**/ "ace/post.h" 00275 00276 #endif /*TAO_CONNECTION_CACHE_MANAGER_H*/