summaryrefslogtreecommitdiff
path: root/TAO/tao/Transport.h
diff options
context:
space:
mode:
Diffstat (limited to 'TAO/tao/Transport.h')
-rw-r--r--TAO/tao/Transport.h191
1 files changed, 176 insertions, 15 deletions
diff --git a/TAO/tao/Transport.h b/TAO/tao/Transport.h
index c318cc2d9b8..c8b9137ff9f 100644
--- a/TAO/tao/Transport.h
+++ b/TAO/tao/Transport.h
@@ -201,9 +201,13 @@ public:
* If any data is to be sent it blocks until the queue is completely
* drained.
*
+ * This method serializes on handler_lock_, guaranteeing that only
+ * thread can execute it on the same instance concurrently.
+ *
* @todo: this routine will probably go away as part of the
* reorganization to support non-blocking writes.
*/
+ // @@ lockme
ssize_t send_or_buffer (TAO_Stub *stub,
int two_way,
const ACE_Message_Block *mblk,
@@ -228,6 +232,7 @@ public:
void buffering_timeout_value (const ACE_Time_Value &time);
/// Send any messages that have been buffered.
+ // @@ lockme
ssize_t send_buffered_messages (const ACE_Time_Value *max_wait_time = 0);
/**
@@ -242,6 +247,14 @@ public:
virtual int bidirectional_flag (void) const;
virtual void bidirectional_flag (int flag);
+ /// Fill in a handle_set with any associated handler's reactor handle.
+ /**
+ * Called by the cache when the cache is closing in order to fill
+ * in a handle_set in a lock-safe manner.
+ * @param handle_set the ACE_Handle_Set into which the transport should place any handle registered with the reactor
+ */
+ void provide_handle (ACE_Handle_Set &handle_set);
+
/// @@ Bala: you must document this function!!
/// @@ Bala: from the implementation in IIOP_Transport it looks more
// like it process the list of listening endpoints, or it is
@@ -254,6 +267,19 @@ public:
*/
void dequeue_all (void);
+ /// Register the handler with the reactor.
+ /**
+ * This method is used by the Wait_On_Reactor strategy. The
+ * transport must register its event handler with the ORB's Reactor.
+ *
+ * @todo: I think this method is pretty much useless, the
+ * connections are *always* registered with the Reactor, except in
+ * thread-per-connection mode. In that case putting the connection
+ * in the Reactor would produce unpredictable results anyway.
+ */
+ // @@ lockme
+ int register_handler (void);
+
/**
* @name Control connection lifecycle
*
@@ -270,8 +296,77 @@ public:
/// now.
virtual int idle_after_reply (void);
+ /// Call the corresponding connection handler's <close>
+ /// method.
+ virtual void close_connection (void);
+
//@}
+ /// Write the complete Message_Block chain to the connection.
+ /**
+ * This method serializes on handler_lock_, guaranteeing that only
+ * thread can execute it on the same instance concurrently.
+ *
+ * Often the implementation simply forwards the arguments to the
+ * underlying ACE_Svc_Handler class. Using the code factored out
+ * into ACE.
+ *
+ * Be careful with protocols that perform non-trivial
+ * transformations of the data, such as SSLIOP or protocols that
+ * compress the stream.
+ *
+ * @param mblk contains the data that must be sent. For each
+ * message block in the cont() chain all the data between rd_ptr()
+ * and wr_ptr() should be delivered to the remote peer.
+ *
+ * @param timeout is the maximum time that the application is
+ * willing to wait for the data to be sent, useful in platforms that
+ * implement timed writes.
+ * The timeout value is obtained from the policies set by the
+ * application.
+ *
+ * @param bytes_transferred should return the total number of bytes
+ * successfully transferred before the connection blocked. This is
+ * required because in some platforms and/or protocols multiple
+ * system calls may be required to send the chain of message
+ * blocks. The first few calls can work successfully, but the final
+ * one can fail or signal a flow control situation (via EAGAIN).
+ * In this case the ORB expects the function to return -1, errno to
+ * be appropriately set and this argument to return the number of
+ * bytes already on the OS I/O subsystem.
+ *
+ * This call can also fail if the transport instance is no longer
+ * associated with a connection (e.g., the connection handler closed
+ * down). In that case, it returns -1 and sets errno to
+ * <code>ENOENT</code>.
+ */
+ ssize_t send (const ACE_Message_Block *mblk,
+ const ACE_Time_Value *timeout = 0,
+ size_t *bytes_transferred = 0);
+
+ /// Read len bytes from into buf.
+ /**
+ * This method serializes on handler_lock_, guaranteeing that only
+ * thread can execute it on the same instance concurrently.
+ *
+ * @param buffer ORB allocated buffer where the data should be
+ * @@ The ACE_Time_Value *s is just a place holder for now. It is
+ * not clear this this is the best place to specify this. The actual
+ * timeout values will be kept in the Policies.
+ */
+ ssize_t recv (char *buffer,
+ size_t len,
+ const ACE_Time_Value *timeout = 0);
+
+
+ /// Return a unique identifier for this transport instance.
+ /**
+ * It's established at construction, and not changed throughout the life
+ * of a transport.
+ */
+ virtual int id (void);
+
+protected:
/** @name Template methods
*
* The Transport class uses the Template Method Pattern to implement
@@ -281,10 +376,7 @@ public:
*/
//@{
- /// Call the corresponding connection handler's <close>
- /// method.
- virtual void close_connection (void);
-
+#if 0
/// Return the file descriptor used for this connection.
/**
* @todo Someday we should be able to support protocols that do not
@@ -296,6 +388,7 @@ public:
* file descriptors.)
*/
virtual ACE_HANDLE handle (void) = 0;
+#endif
/// Return the event handler used to receive notifications from the
/// Reactor.
@@ -312,7 +405,9 @@ public:
* will reduce footprint and simplify the process of implementing a
* pluggable protocol.
*/
- virtual ACE_Event_Handler *event_handler (void) = 0;
+ // @@ this is broken once we add the lock b/c it returns the thing
+ // we're trying to lock down! (CJC)
+ virtual ACE_Event_Handler *event_handler_i (void) = 0;
/// Write the complete Message_Block chain to the connection.
/**
@@ -345,9 +440,9 @@ public:
* bytes already on the OS I/O subsystem.
*
*/
- virtual ssize_t send (const ACE_Message_Block *mblk,
- const ACE_Time_Value *timeout = 0,
- size_t *bytes_transferred = 0) = 0;
+ virtual ssize_t send_i (const ACE_Message_Block *mblk,
+ const ACE_Time_Value *timeout = 0,
+ size_t *bytes_transferred = 0) = 0;
// Read len bytes from into buf.
/**
@@ -356,15 +451,17 @@ public:
* not clear this this is the best place to specify this. The actual
* timeout values will be kept in the Policies.
*/
- virtual ssize_t recv (char *buffer,
- size_t len,
- const ACE_Time_Value *timeout = 0) = 0;
+ virtual ssize_t recv_i (char *buffer,
+ size_t len,
+ const ACE_Time_Value *timeout = 0) = 0;
+public:
/// Fill into <output> the right headers to make a request.
/**
* @todo Bala: in the good old days it was decided that the
* pluggable protocol framework would not raise exceptions.
*/
+ // @nolock
virtual void start_request (TAO_ORB_Core *orb_core,
TAO_Target_Specification &spec,
TAO_OutputCDR &output,
@@ -377,6 +474,7 @@ public:
* @todo Bala: in the good old days it was decided that the
* pluggable protocol framework would not raise exceptions.
*/
+ // @@nolock
virtual void start_locate (TAO_ORB_Core *orb_core,
TAO_Target_Specification &spec,
TAO_Operation_Details &opdetails,
@@ -410,6 +508,7 @@ public:
* @todo This is generic code, it should be factored out into the
* Transport class.
*/
+ // @nolock b/c this calls send_or_buffer
virtual int send_request (TAO_Stub *stub,
TAO_ORB_Core *orb_core,
TAO_OutputCDR &stream,
@@ -439,6 +538,7 @@ public:
*
* @todo Another generic method, move to TAO_Transport.
*/
+ // @@ lockme
virtual int send_message (TAO_OutputCDR &stream,
TAO_Stub *stub = 0,
int twoway = 1,
@@ -463,9 +563,11 @@ public:
* @param block Is deprecated and ignored.
*
*/
+ // @@ lockme
virtual int read_process_message (ACE_Time_Value *max_wait_time = 0,
int block = 0) = 0;
+protected:
/// Register the handler with the reactor.
/**
* This method is used by the Wait_On_Reactor strategy. The
@@ -476,8 +578,20 @@ public:
* thread-per-connection mode. In that case putting the connection
* in the Reactor would produce unpredictable results anyway.
*/
- virtual int register_handler (void) = 0;
+ // @@ lockme
+ virtual int register_handler_i (void) = 0;
+
+ /// Called by <code>connection_handler_closing()</code> to signal
+ /// that the protocol-specific transport should dissociate itself
+ /// with the protocol-specific connection handler.
+ /**
+ * Typically, this just sets the pointer to the associated connection
+ * handler to zero, although it could also clear out any additional
+ * resources associated with the handler association.
+ */
+ virtual void transition_handler_state_i (void) = 0;
+public:
/// Indicates whether the reactor is used by the protocol for
/// signalling.
/**
@@ -491,10 +605,27 @@ public:
/// Method for the connection handler to signify that it
/// is being closed and destroyed.
virtual void connection_handler_closing (void);
- virtual void transition_handler_state (void) = 0;
- // Access the connection handler
- virtual TAO_Connection_Handler* connection_handler (void) const;
+ /// Register the associated connection handler with the reactor
+ /// for a timer.
+ /**
+ * At this point, only <code>TAO_Eager_Buffering_Sync_Strategy::timer_check()</code>
+ * uses this, and it's unclear whether it needs to stay around. But, it's here
+ * because it uses the associated protocol-specific connection handler, and accesses
+ * to that must be serialized on the internal lock.
+ *
+ * @param arg argument passed to the handle_timeout() method of the event handler
+ * @param delay time interval after which the timer will expire
+ * @param interval time interval after which the timer will be automatically rescheduled
+ * @return -1 on failure, a Reactor timer_id value on success
+ *
+ * @see ACE_Reactor::schedule_timer()
+ * @see TAO_Eager_Buffering_Sync_Strategy::timer_check()
+ */
+ long register_for_timer_event (const void* arg,
+ const ACE_Time_Value &delay,
+ const ACE_Time_Value &interval = ACE_Time_Value::zero);
+
// Maintain reference counting with these
static TAO_Transport* _duplicate (TAO_Transport* transport);
@@ -514,6 +645,13 @@ public:
int make_idle (void);
protected:
+#if 0
+ // Access the connection handler
+ // @@CJC Do we still need this?!
+ virtual TAO_Connection_Handler* connection_handler_i (void) const;
+#endif
+
+ // @@ see if one of these calls send_message()
/// Remove the first message from the outgoing queue.
void dequeue_head (void);
@@ -531,6 +669,7 @@ protected:
void reset_message (ACE_Message_Block *message_block,
size_t bytes_delivered,
int queued_message);
+
private:
/// Prohibited
ACE_UNIMPLEMENTED_FUNC (TAO_Transport (const TAO_Transport&))
@@ -584,6 +723,28 @@ protected:
* if the server receives the info.
*/
int bidirectional_flag_;
+
+ /// Lock that insures that activities that *might* use handler-related
+ /// resources (such as a connection handler) get serialized.
+ /**
+ * This is an <code>ACE_Lock</code> that gets initialized from
+ * <code>TAO_ORB_Core::resource_factory()->create_cached_connection_lock ()</code>.
+ * This way, one can use a lock appropriate for the type of system, i.e.,
+ * a null lock for single-threaded systems, and a real lock for
+ * multi-threaded systems.
+ */
+ ACE_Lock *handler_lock_;
+
+ /// A unique identifier for the transport.
+ /**
+ * This never *never*
+ * changes over the lifespan, so we don't have to worry
+ * about locking it.
+ *
+ * HINT: Protocol-specific transports that use connection handler
+ * might choose to set this to the handle for their connection.
+ */
+ int id_;
};
#if defined (__ACE_INLINE__)