diff options
author | bala <balanatarajan@users.noreply.github.com> | 2002-11-29 16:35:30 +0000 |
---|---|---|
committer | bala <balanatarajan@users.noreply.github.com> | 2002-11-29 16:35:30 +0000 |
commit | e1b76a559b3727d2fa4b11f2a6645e8e49c8d589 (patch) | |
tree | e2db99d42f7c9c99984d987a89fa6ad187e4ce6f | |
parent | 90966fe44ad459bd8fdae968bcdf99ac19d0dad9 (diff) | |
download | ATCD-e1b76a559b3727d2fa4b11f2a6645e8e49c8d589.tar.gz |
ChangeLogTag: Fri Nov 29 11:16:28 2002 Balachandran Natarajan <bala@isis-server.isis.vanderbilt.edu>
-rw-r--r-- | TAO/ChangeLog | 56 | ||||
-rw-r--r-- | TAO/tao/Connection_Handler.cpp | 31 | ||||
-rw-r--r-- | TAO/tao/Connection_Handler.h | 4 | ||||
-rw-r--r-- | TAO/tao/IIOP_Connection_Handler.cpp | 9 | ||||
-rw-r--r-- | TAO/tao/LF_CH_Event.cpp | 34 | ||||
-rw-r--r-- | TAO/tao/LF_CH_Event.h | 46 | ||||
-rw-r--r-- | TAO/tao/LF_Event.h | 3 | ||||
-rw-r--r-- | TAO/tao/Transport.cpp | 10 | ||||
-rw-r--r-- | TAO/tao/Transport.h | 9 | ||||
-rw-r--r-- | TAO/tao/Transport_Cache_Manager.cpp | 26 | ||||
-rw-r--r-- | TAO/tao/Transport_Cache_Manager.h | 19 | ||||
-rw-r--r-- | TAO/tao/Transport_Cache_Manager.inl | 45 |
12 files changed, 256 insertions, 36 deletions
diff --git a/TAO/ChangeLog b/TAO/ChangeLog index e53d42f5013..29b7b49cb0f 100644 --- a/TAO/ChangeLog +++ b/TAO/ChangeLog @@ -1,3 +1,59 @@ +Fri Nov 29 11:16:28 2002 Balachandran Natarajan <bala@isis-server.isis.vanderbilt.edu> + + This set of fixes are for fixing BUG 1247. Please see + + http://deuce.doc.wustl.edu/bugzilla/show_bug.cgi?id=1247 + for more details. The problem is that the server side connections + never got purged. The cache manager was designed to purge + connections in the client and server end. + + * tao/Transport_Cache_Manager.h: + * tao/Transport_Cache_Manager.cpp: + * tao/transport_cache_manager.inl: Added two new methods, + cache_idle_transport () and update_entry (). The former + caches the transport and puts it in the idle and purgable + state. The latter is useful to update the purge policy + information. + + * tao/Transport.h: + * tao/Transport.cpp: Added a new method update_transport () which + in turn calls the TAO_Transport_Cache_Manager::update_entry () + to update the purging policy information. + + In close_connection_shared (), the connection handler is set in + a temporary state before waiting on the LF for connection + closure. + + * tao/Connection_Handler.cpp (TAO_Connection_Handler): + * tao/Connection_Handler.h: Added a new method + connection_close_wait () to set the connection handler in a + a state which is an intermediate state between SUCESS and + CONNECTION_CLOSED. + + Added a call to update transport information in handle_output_eh + () and handle_input_eh (). This is needed for the following + reasons + + . A connection could be cached by a server thread and the + connection would be continously used to receive requests. In + such cases the cache and purging policies should be updated + to ensure that actively used connections are not purged. + + . In BiDirectional cases, a client thread could cache the + connection, but the connection could be actively used by a + server thread. An update is needed to avoid purging the + connections abruptly. + + * tao/IIOP_Connection_Handler.cpp: Cache and idle the transport in + add_transport_to_cache () instead of just caching and leaving + the transport in busy state. + + * tao/LF_Event.h: + * tao/LF_CH_Event.h: + * tao/LF_CH_Event.cpp: Added a new temporary state in the path + from LFS_SUCCESS to LFS_CONNECTION_CLOSED. + + Fri Nov 29 09:56:46 2002 Balachandran Natarajan <bala@isis-server.isis.vanderbilt.edu> * tests/OBV/Any/client.cpp: diff --git a/TAO/tao/Connection_Handler.cpp b/TAO/tao/Connection_Handler.cpp index e304818b7d2..78ded37f522 100644 --- a/TAO/tao/Connection_Handler.cpp +++ b/TAO/tao/Connection_Handler.cpp @@ -204,6 +204,15 @@ TAO_Connection_Handler::decr_refcount (void) return 0; } +void +TAO_Connection_Handler::connection_close_wait (void) +{ + ACE_GUARD (ACE_Lock, ace_mon, *this->lock_); + this->state_changed (TAO_LF_Event::LFS_CONNECTION_CLOSE_WAIT); +} + + + int TAO_Connection_Handler::handle_close_eh ( ACE_HANDLE handle, unsigned long reactor_mask, ACE_Event_Handler * eh) @@ -241,6 +250,14 @@ int TAO_Connection_Handler::handle_output_eh ( ACE_HANDLE, ACE_Event_Handler * eh) { + // We are going to use the transport object to write data. Just make + // sure that we have transport objects to proceed. This is + // perfectly valid assert + ACE_ASSERT (this->transport () != 0); + + // Let the transport that it is going to be used + (void) this->transport ()->update_transport (); + // Instantiate the resume handle here.. This will automatically // resume the handle once data is written.. TAO_Resume_Handle resume_handle (this->orb_core (), @@ -269,6 +286,15 @@ int TAO_Connection_Handler::handle_input_eh ( ACE_HANDLE h, ACE_Event_Handler * eh) { + // We are going to use the transport object to read data. Just make + // sure that we have transport objects to proceed. This is + // perfectly valid assert + ACE_ASSERT (this->transport () != 0); + + // Let the transport know that it is used + (void) this->transport ()->update_transport (); + + // Increase the reference count on the upcall that have passed us. // // REFCNT: Matches decr_refcount() in this function... @@ -281,7 +307,7 @@ TAO_Connection_Handler::handle_input_eh ( ACE_DEBUG ((LM_DEBUG, "TAO (%P|%t) - Connection_Handler[%d]::handle_input, " "handle = %d/%d, refcount = %d\n", - this->transport()->id(), handle, h, refcount)); + this->transport ()->id (), handle, h, refcount)); } TAO_Resume_Handle resume_handle (this->orb_core (), eh->get_handle ()); @@ -297,6 +323,7 @@ TAO_Connection_Handler::handle_input_eh ( return return_value; } + return_value = this->transport ()->handle_input_i (resume_handle); this->pos_io_hook(return_value); @@ -311,7 +338,7 @@ TAO_Connection_Handler::handle_input_eh ( ACE_DEBUG ((LM_DEBUG, "TAO (%P|%t) Connection_Handler[%d]::handle_input, " "handle = %d/%d, refcount = %d, retval = %d\n", - this->transport()->id(), handle, h, refcount, return_value)); + this->transport()->id (), handle, h, refcount, return_value)); } if (return_value == -1 || refcount == 0) diff --git a/TAO/tao/Connection_Handler.h b/TAO/tao/Connection_Handler.h index a54eeee6ae9..81e7f7a2887 100644 --- a/TAO/tao/Connection_Handler.h +++ b/TAO/tao/Connection_Handler.h @@ -72,6 +72,10 @@ public: long incr_refcount (void); long decr_refcount (void); + /// Set the handler in <CODE>LF_EVENT_CONNECTION_CLOSE_WAIT </CODE> + /// state + void connection_close_wait (void); + /// Close the underlying connection. /** * Used by the ORB to actively close connections that are idle, diff --git a/TAO/tao/IIOP_Connection_Handler.cpp b/TAO/tao/IIOP_Connection_Handler.cpp index aca7dd13b27..0e116beafbd 100644 --- a/TAO/tao/IIOP_Connection_Handler.cpp +++ b/TAO/tao/IIOP_Connection_Handler.cpp @@ -243,9 +243,12 @@ TAO_IIOP_Connection_Handler::add_transport_to_cache (void) // Construct a property object TAO_Base_Transport_Property prop (&endpoint); - // Add the handler to Cache - return this->orb_core ()->lane_resources ().transport_cache ().cache_transport (&prop, - this->transport ()); + TAO_Transport_Cache_Manager &cache = + this->orb_core ()->lane_resources ().transport_cache (); + + // Idle the transport.. + return cache.cache_idle_transport (&prop, + this->transport ()); } int diff --git a/TAO/tao/LF_CH_Event.cpp b/TAO/tao/LF_CH_Event.cpp index 45f6596d31b..f4e1551b881 100644 --- a/TAO/tao/LF_CH_Event.cpp +++ b/TAO/tao/LF_CH_Event.cpp @@ -48,14 +48,31 @@ TAO_LF_CH_Event::state_changed_i (int new_state) } else if (this->state_ == TAO_LF_Event::LFS_SUCCESS) { - if (new_state == TAO_LF_Event::LFS_CONNECTION_CLOSED) + if (new_state == TAO_LF_Event::LFS_CONNECTION_CLOSE_WAIT + || new_state == TAO_LF_Event::LFS_CONNECTION_CLOSED) { this->prev_state_ = this->state_; this->state_ = new_state; } return; } - + else if (this->state_ == TAO_LF_Event::LFS_CONNECTION_CLOSE_WAIT) + { + if (new_state == TAO_LF_Event::LFS_CONNECTION_CLOSED) + { + // Dont reset the previous state. We could have come only + // from SUCESS. Let that state be preserved. + this->state_ = new_state; + } + } + else if (this->state_ == TAO_LF_Event::LFS_TIMEOUT) + { + if (new_state == TAO_LF_Event::LFS_CONNECTION_CLOSED) + { + // Dont reset the previous state + this->state_ = new_state; + } + } return; } @@ -65,10 +82,8 @@ TAO_LF_CH_Event::successful (void) const { if (this->prev_state_ == TAO_LF_Event::LFS_CONNECTION_WAIT) return this->state_ == TAO_LF_Event::LFS_SUCCESS; - else if (this->prev_state_ == TAO_LF_Event::LFS_SUCCESS) - return this->state_ == TAO_LF_Event::LFS_CONNECTION_CLOSED; - return 0; + return this->state_ == TAO_LF_Event::LFS_CONNECTION_CLOSED; } int @@ -76,7 +91,7 @@ TAO_LF_CH_Event::error_detected (void) const { if (this->prev_state_ == TAO_LF_Event::LFS_CONNECTION_WAIT) return this->state_ == TAO_LF_Event::LFS_CONNECTION_CLOSED; - else if (this->prev_state_ == TAO_LF_Event::LFS_SUCCESS) + else if (this->prev_state_ == TAO_LF_Event::LFS_CONNECTION_CLOSE_WAIT) return (this->state_ != TAO_LF_Event::LFS_CONNECTION_CLOSED); return 0; @@ -85,8 +100,11 @@ TAO_LF_CH_Event::error_detected (void) const void TAO_LF_CH_Event::set_state (int new_state) { - this->prev_state_ = this->state_; - this->state_ = new_state; + if (this->is_state_final () == 0 + && new_state == TAO_LF_Event::LFS_TIMEOUT) + { + this->state_ = new_state; + } } diff --git a/TAO/tao/LF_CH_Event.h b/TAO/tao/LF_CH_Event.h index 0ac940f66dc..5fa376d5d82 100644 --- a/TAO/tao/LF_CH_Event.h +++ b/TAO/tao/LF_CH_Event.h @@ -56,18 +56,40 @@ private: * This concrete class uses the following states declared in the * class TAO_LF_Event to transition states * - * LFS_IDLE - The event is created, and is in initial - * state. - * LFS_CONNECTION_WAIT - The event is waiting for connection - * completion and it can transition to any of - * the following states, all the states are - * final. - * LFS_SUCCESS - The event, connection establishment, has - * completed successfully. - * LFS_TIMEOUT - The event has timed out. - * LFS_CONNECTION_CLOSED - The connection was closed since an error - * occured while trying to establish - * connection + * LFS_IDLE - The event is created, and is in + * initial state. + * + * LFS_CONNECTION_WAIT - The event is waiting for connection + * completion and it can transition to + * any of the following states, all the + * states are final. + * + * LFS_SUCCESS - The event, connection establishment, has + * completed successfully. + * + * LFS_TIMEOUT - The event has timed out. + * + * LFS_CONNECTION_CLOSE_WAIT - A temporary state before complete + * connection closure. An event + * handler in this state is supposed to + * be getting ready for closure. + * + * LFS_CONNECTION_CLOSED - The connection was closed since + * an error occured while trying to + * establish connection + * + * Event State Diagram + * ------------------- + * |----> CLOSED <-| + * | ^ | + * | | | + * IDLE ---> CONNECTION_WAIT-| | CLOSE_WAIT + * | | ^ + * | | | + * |----> SUCESS---> + * + * Timeouts can occur while waiting for connections or during + * CLOSE_WAIT state. * */ virtual void state_changed_i (int new_state); diff --git a/TAO/tao/LF_Event.h b/TAO/tao/LF_Event.h index 6dd77f6e23b..c6d919a333a 100644 --- a/TAO/tao/LF_Event.h +++ b/TAO/tao/LF_Event.h @@ -89,6 +89,9 @@ public: LFS_FAILURE, /// The event has timed out LFS_TIMEOUT, + /// The event is waiting for connection closure. This is a + /// temporary state + LFS_CONNECTION_CLOSE_WAIT, /// The connection was closed. LFS_CONNECTION_CLOSED }; diff --git a/TAO/tao/Transport.cpp b/TAO/tao/Transport.cpp index 24dc9e08246..ccc4259d486 100644 --- a/TAO/tao/Transport.cpp +++ b/TAO/tao/Transport.cpp @@ -349,6 +349,7 @@ TAO_Transport::connection_handler_closing (void) } } +// @@TODO: Ideally the following should be inline. int TAO_Transport::recache_transport (TAO_Transport_Descriptor_Interface *desc) { @@ -370,8 +371,12 @@ int TAO_Transport::make_idle (void) { return this->transport_cache_manager ().make_idle (this->cache_map_entry_); +} - return -1; +int +TAO_Transport::update_transport (void) +{ + return this->transport_cache_manager ().update_entry (this->cache_map_entry_); } @@ -698,6 +703,9 @@ TAO_Transport::close_connection_shared (int purge, int retval = 0; + // Set the event handler in the connection close wait state. + (void) eh->connection_close_wait (); + // NOTE: If the wait strategy is in blocking mode, then there is no // chance that it could be inside the reactor. We can safely skip // driving the LF. diff --git a/TAO/tao/Transport.h b/TAO/tao/Transport.h index ca66d29e2fb..61deb876b5c 100644 --- a/TAO/tao/Transport.h +++ b/TAO/tao/Transport.h @@ -631,9 +631,9 @@ public: * block, used in the implementation of timeouts. */ virtual int send_message_shared (TAO_Stub *stub, - int message_semantics, - const ACE_Message_Block *message_block, - ACE_Time_Value *max_wait_time); + int message_semantics, + const ACE_Message_Block *message_block, + ACE_Time_Value *max_wait_time); protected: @@ -740,6 +740,9 @@ public: /// Cache management int make_idle (void); + /// Cache management + int update_transport (void); + /// The timeout callback, invoked when any of the timers related to /// this transport expire. /** diff --git a/TAO/tao/Transport_Cache_Manager.cpp b/TAO/tao/Transport_Cache_Manager.cpp index 3388cbdbc9d..f0c3d5e334d 100644 --- a/TAO/tao/Transport_Cache_Manager.cpp +++ b/TAO/tao/Transport_Cache_Manager.cpp @@ -97,9 +97,7 @@ TAO_Transport_Cache_Manager::bind_i (TAO_Cache_ExtId &ext_id, // are holding our lock this->purging_strategy_->update_item (int_id.transport ()); - // When it comes for bind we know the transport is going to be busy - // and is marked for a partcular thread. So, mark it busy - int_id.recycle_state (ACE_RECYCLABLE_BUSY); + int retval = this->cache_map_.bind (ext_id, int_id, @@ -299,6 +297,21 @@ TAO_Transport_Cache_Manager::make_idle_i (HASH_MAP_ENTRY *&entry) int +TAO_Transport_Cache_Manager::update_entry (HASH_MAP_ENTRY *&entry) +{ + if(entry == 0) + return -1; + + ACE_MT (ACE_GUARD_RETURN (ACE_Lock, + guard, + *this->cache_lock_, -1)); + + (void) this->purging_strategy_->update_item (entry->int_id_.transport ()); + + return 0; +} + +int TAO_Transport_Cache_Manager::close_i (ACE_Handle_Set &reactor_registered, TAO_EventHandlerSet &unregistered) { @@ -387,6 +400,13 @@ TAO_Transport_Cache_Manager::get_last_index_bind (TAO_Cache_ExtId &key, int TAO_Transport_Cache_Manager::is_entry_idle (HASH_MAP_ENTRY *&entry) { + if (TAO_debug_level) + { + ACE_DEBUG ((LM_DEBUG, + "TAO (%P|%t) - Transport_Cache_Manager::is_entry_idle_i, " + "state is [%d]\n", + entry->int_id_.recycle_state ())); + } if (entry->int_id_.recycle_state () == ACE_RECYCLABLE_IDLE_AND_PURGABLE || entry->int_id_.recycle_state () == ACE_RECYCLABLE_IDLE_BUT_NOT_PURGABLE) { diff --git a/TAO/tao/Transport_Cache_Manager.h b/TAO/tao/Transport_Cache_Manager.h index 5a87d7f7e72..3b0ac6b9263 100644 --- a/TAO/tao/Transport_Cache_Manager.h +++ b/TAO/tao/Transport_Cache_Manager.h @@ -79,11 +79,22 @@ public: /// Destructor virtual ~TAO_Transport_Cache_Manager (void); - /// Add the transport to the cache. The transport has the property - /// definition based on which caching can be done + /// Add the transport to the cache. + + /** + * The transport has the property definition based on which caching + * can be done. This method marks the transport + * <CODE>ACE_RECYCLABLE_BUSY </CODE> which helps the threads + * opening up connections to use the transport immediately. + */ int cache_transport (TAO_Transport_Descriptor_Interface *prop, TAO_Transport *transport); + /// Similar to the one above, but the transport is left in <CODE> + /// ACE_RECYCLABLE_IDLE_AND_PURGABLE</CODE> state. + int cache_idle_transport (TAO_Transport_Descriptor_Interface *prop, + TAO_Transport *transport); + /// Check the Transport Cache to check whether the connection exists /// in the Cache and return the connection int find_transport (TAO_Transport_Descriptor_Interface *prop, @@ -101,6 +112,10 @@ public: /// Make the entry idle and ready for use. int make_idle (HASH_MAP_ENTRY *&entry); + /// Mark the entry as touched. This call updates the purging + /// strategy policy information. + int update_entry (HASH_MAP_ENTRY *&entry); + /// Close the underlying hash map manager and return the handle set /// that have been registered with the reactor int close (ACE_Handle_Set &reactor_registered, diff --git a/TAO/tao/Transport_Cache_Manager.inl b/TAO/tao/Transport_Cache_Manager.inl index c32192b6998..1285d173d22 100644 --- a/TAO/tao/Transport_Cache_Manager.inl +++ b/TAO/tao/Transport_Cache_Manager.inl @@ -24,9 +24,48 @@ TAO_Transport_Cache_Manager::cache_transport ( TAO_Cache_ExtId ext_id (prop); TAO_Cache_IntId int_id (transport); - return this->bind (ext_id, - int_id); + int retval = 0; + { + ACE_MT (ACE_GUARD_RETURN (ACE_Lock, + guard, + *this->cache_lock_, + -1)); + // Do as the semantics of this method dictates + int_id.recycle_state (ACE_RECYCLABLE_BUSY); + + retval = this->bind_i (ext_id, + int_id); + } + + return retval; +} + +ACE_INLINE int +TAO_Transport_Cache_Manager::cache_idle_transport ( + TAO_Transport_Descriptor_Interface *prop, + TAO_Transport *transport) +{ + // Compose the ExternId & Intid + TAO_Cache_ExtId ext_id (prop); + TAO_Cache_IntId int_id (transport); + + int retval = 0; + { + ACE_MT (ACE_GUARD_RETURN (ACE_Lock, + guard, + *this->cache_lock_, + -1)); + + // Do as the semantics of this method dictates + int_id.recycle_state (ACE_RECYCLABLE_IDLE_AND_PURGABLE); + retval = this->bind_i (ext_id, + int_id); + + + } + + return retval; } ACE_INLINE int @@ -85,6 +124,8 @@ TAO_Transport_Cache_Manager::make_idle (HASH_MAP_ENTRY *&entry) } + + ACE_INLINE int TAO_Transport_Cache_Manager::close (ACE_Handle_Set &reactor_registered, TAO_EventHandlerSet &unregistered) |