summaryrefslogtreecommitdiff
path: root/TAO
diff options
context:
space:
mode:
authorbala <balanatarajan@users.noreply.github.com>2002-11-29 16:35:30 +0000
committerbala <balanatarajan@users.noreply.github.com>2002-11-29 16:35:30 +0000
commite1b76a559b3727d2fa4b11f2a6645e8e49c8d589 (patch)
treee2db99d42f7c9c99984d987a89fa6ad187e4ce6f /TAO
parent90966fe44ad459bd8fdae968bcdf99ac19d0dad9 (diff)
downloadATCD-e1b76a559b3727d2fa4b11f2a6645e8e49c8d589.tar.gz
ChangeLogTag: Fri Nov 29 11:16:28 2002 Balachandran Natarajan <bala@isis-server.isis.vanderbilt.edu>
Diffstat (limited to 'TAO')
-rw-r--r--TAO/ChangeLog56
-rw-r--r--TAO/tao/Connection_Handler.cpp31
-rw-r--r--TAO/tao/Connection_Handler.h4
-rw-r--r--TAO/tao/IIOP_Connection_Handler.cpp9
-rw-r--r--TAO/tao/LF_CH_Event.cpp34
-rw-r--r--TAO/tao/LF_CH_Event.h46
-rw-r--r--TAO/tao/LF_Event.h3
-rw-r--r--TAO/tao/Transport.cpp10
-rw-r--r--TAO/tao/Transport.h9
-rw-r--r--TAO/tao/Transport_Cache_Manager.cpp26
-rw-r--r--TAO/tao/Transport_Cache_Manager.h19
-rw-r--r--TAO/tao/Transport_Cache_Manager.inl45
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)