TAO  2.2.6
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Classes | Public Types | Public Member Functions | List of all members
TAO_Transport Class Referenceabstract

Generic definitions for the Transport class. More...

#include <Transport.h>

Inheritance diagram for TAO_Transport:
Inheritance graph
Collaboration diagram for TAO_Transport:
Collaboration graph

Classes

struct  Drain_Result
 

Public Types

enum  Drain_Result_Enum { DR_ERROR = -1, DR_OK = 0, DR_QUEUE_EMPTY = 1, DR_WOULDBLOCK = 2 }
 

Public Member Functions

 TAO_Transport (CORBA::ULong tag, TAO_ORB_Core *orb_core, size_t input_cdr_size=ACE_CDR::DEFAULT_BUFSIZE)
 Default creator, requires the tag value be supplied. More...
 
virtual ~TAO_Transport (void)
 Destructor. More...
 
CORBA::ULong tag (void) const
 Return the protocol tag. More...
 
TAO_ORB_Coreorb_core (void) const
 Access the ORB that owns this connection. More...
 
TAO_Transport_Mux_Strategytms (void) const
 Get the TAO_Tranport_Mux_Strategy used by this object. More...
 
TAO_Wait_Strategywait_strategy (void) const
 Return the TAO_Wait_Strategy used by this object. More...
 
Drain_Result handle_output (TAO::Transport::Drain_Constraints const &c)
 Callback method to reactively drain the outgoing data queue. More...
 
int bidirectional_flag (void) const
 Get the bidirectional flag. More...
 
void bidirectional_flag (int flag)
 Set the bidirectional flag. More...
 
void cache_map_entry (TAO::Transport_Cache_Manager::HASH_MAP_ENTRY *entry)
 Set the Cache Map entry. More...
 
TAO::Transport_Cache_Manager::HASH_MAP_ENTRYcache_map_entry (void)
 Get the Cache Map entry. More...
 
size_t id (void) const
 Set and Get the identifier for this transport instance. More...
 
void id (size_t id)
 
TAO::Connection_Role opened_as (void) const
 
void opened_as (TAO::Connection_Role)
 
unsigned long purging_order (void) const
 
void purging_order (unsigned long value)
 
bool queue_is_empty (void)
 Check if there are messages pending in the queue. More...
 
bool register_if_necessary (void)
 Register with the reactor via the wait strategy. More...
 
void provide_handler (TAO::Connection_Handler_Set &handlers)
 Added event handler to the handlers set. More...
 
bool provide_blockable_handler (TAO::Connection_Handler_Set &handlers)
 
virtual int register_handler (void)
 Register the handler with the reactor. More...
 
virtual int remove_handler (void)
 Remove the handler from the reactor. More...
 
virtual ssize_t send (iovec *iov, int iovcnt, size_t &bytes_transferred, ACE_Time_Value const *timeout)=0
 Write the complete Message_Block chain to the connection. More...
 
virtual ssize_t recv (char *buffer, size_t len, const ACE_Time_Value *timeout=0)=0
 Read len bytes from into buf. More...
 
Control connection lifecycle

These methods are routed through the TMS object. The TMS strategies implement them correctly.

bool idle_after_send (void)
 
bool idle_after_reply (void)
 
virtual void close_connection (void)
 Call the implementation method after obtaining the lock. More...
 

Template methods

The Transport class uses the Template Method Pattern to implement the protocol specific functionality. Implementors of a pluggable protocol should override the following methods with the semantics documented below.

class TAO_Reactive_Flushing_Strategy
 
class TAO_Leader_Follower_Flushing_Strategy
 
class TAO_Thread_Per_Connection_Handler
 
CORBA::ULong const tag_
 IOP protocol tag. More...
 
TAO_ORB_Core *const orb_core_
 Global orbcore resource. More...
 
TAO::Transport_Cache_Manager::HASH_MAP_ENTRYcache_map_entry_
 
TAO_Transport_Mux_Strategytms_
 
TAO_Wait_Strategyws_
 Strategy for waiting for the reply after sending the request. More...
 
int bidirectional_flag_
 
TAO::Connection_Role opening_connection_role_
 
TAO_Queued_Messagehead_
 Implement the outgoing data queue. More...
 
TAO_Queued_Messagetail_
 
TAO_Incoming_Message_Queue incoming_message_queue_
 Queue of the consolidated, incoming messages.. More...
 
TAO::Incoming_Message_Stack incoming_message_stack_
 
ACE_Time_Value current_deadline_
 
long flush_timer_id_
 The timer ID. More...
 
TAO_Transport_Timer transport_timer_
 The adapter used to receive timeout callbacks from the Reactor. More...
 
ACE_Lockhandler_lock_
 
size_t id_
 A unique identifier for the transport. More...
 
unsigned long purging_order_
 Used by the LRU, LFU and FIFO Connection Purging Strategies. More...
 
size_t recv_buffer_size_
 Size of the buffer received. More...
 
size_t sent_byte_count_
 Number of bytes sent. More...
 
bool is_connected_
 
bool connection_closed_on_read_
 
TAO_GIOP_Message_Basemessaging_object_
 Our messaging object. More...
 
TAO_Codeset_Translator_Basechar_translator_
 Additional member values required to support codeset translation. More...
 
TAO_Codeset_Translator_Basewchar_translator_
 
CORBA::Boolean tcs_set_
 
bool first_request_
 
ACE_Message_Blockpartial_message_
 Holds the partial GIOP message (if there is one) More...
 
TAO::Transport::Statsstats_
 Statistics. More...
 
bool flush_in_post_open_
 Indicate that flushing needs to be done in post_open() More...
 
TAO_SYNCH_MUTEX output_cdr_mutex_
 lock for synchronizing Transport OutputCDR access More...
 
void messaging_init (TAO_GIOP_Message_Version const &version)
 
virtual int tear_listen_point_list (TAO_InputCDR &cdr)
 
virtual bool post_connect_hook (void)
 Hooks that can be overridden in concrete transports. More...
 
ACE_Event_Handler::Reference_Count add_reference (void)
 Memory management routines. More...
 
ACE_Event_Handler::Reference_Count remove_reference (void)
 
TAO_GIOP_Message_Basemessaging_object (void)
 
virtual ACE_Event_Handlerevent_handler_i (void)=0
 
bool is_connected (void) const
 Is this transport really connected. More...
 
bool connection_closed_on_read (void) const
 Was a connection seen as closed during a read. More...
 
bool post_open (size_t id)
 Perform all the actions when this transport get opened. More...
 
void pre_close (void)
 do what needs to be done when closing the transport More...
 
TAO_Connection_Handlerconnection_handler (void)
 Get the connection handler for this transport. More...
 
TAO_OutputCDRout_stream (void)
 Accessor for the output CDR stream. More...
 
TAO_SYNCH_MUTEXoutput_cdr_lock (void)
 Accessor for synchronizing Transport OutputCDR access. More...
 
bool can_be_purged (void)
 Can the transport be purged? More...
 
virtual void set_bidir_context_info (TAO_Operation_Details &opdetails)
 
int generate_locate_request (TAO_Target_Specification &spec, TAO_Operation_Details &opdetails, TAO_OutputCDR &output)
 
virtual int generate_request_header (TAO_Operation_Details &opd, TAO_Target_Specification &spec, TAO_OutputCDR &msg)
 
int recache_transport (TAO_Transport_Descriptor_Interface *desc)
 Recache ourselves in the cache. More...
 
virtual int handle_input (TAO_Resume_Handle &rh, ACE_Time_Value *max_wait_time=0)
 Callback to read incoming data. More...
 
virtual int send_request (TAO_Stub *stub, TAO_ORB_Core *orb_core, TAO_OutputCDR &stream, TAO_Message_Semantics message_semantics, ACE_Time_Value *max_time_wait)=0
 
virtual int send_message (TAO_OutputCDR &stream, TAO_Stub *stub=0, TAO_ServerRequest *request=0, TAO_Message_Semantics message_semantics=TAO_Message_Semantics(), ACE_Time_Value *max_time_wait=0)=0
 
virtual int send_message_shared (TAO_Stub *stub, TAO_Message_Semantics message_semantics, const ACE_Message_Block *message_block, ACE_Time_Value *max_wait_time)
 Sent the contents of message_block. More...
 
int format_queue_message (TAO_OutputCDR &stream, ACE_Time_Value *max_wait_time, TAO_Stub *stub)
 
int send_message_block_chain (const ACE_Message_Block *message_block, size_t &bytes_transferred, ACE_Time_Value *max_wait_time=0)
 
int send_message_block_chain_i (const ACE_Message_Block *message_block, size_t &bytes_transferred, TAO::Transport::Drain_Constraints const &dc)
 Send a message block chain, assuming the lock is held. More...
 
int purge_entry (void)
 Cache management. More...
 
int make_idle (void)
 Cache management. More...
 
int update_transport (void)
 Cache management. More...
 
int handle_timeout (const ACE_Time_Value &current_time, const void *act)
 
size_t recv_buffer_size (void) const
 Accessor to recv_buffer_size_. More...
 
size_t sent_byte_count (void) const
 Accessor to sent_byte_count_. More...
 
TAO_Codeset_Translator_Basechar_translator (void) const
 CodeSet Negotiation - Get the char codeset translator factory. More...
 
TAO_Codeset_Translator_Basewchar_translator (void) const
 CodeSet Negotiation - Get the wchar codeset translator factory. More...
 
void char_translator (TAO_Codeset_Translator_Base *)
 CodeSet negotiation - Set the char codeset translator factory. More...
 
void wchar_translator (TAO_Codeset_Translator_Base *)
 CodeSet negotiation - Set the wchar codeset translator factory. More...
 
void assign_translators (TAO_InputCDR *, TAO_OutputCDR *)
 
void clear_translators (TAO_InputCDR *, TAO_OutputCDR *)
 
CORBA::Boolean is_tcs_set () const
 Return true if the tcs has been set. More...
 
void first_request_sent (bool flag=false)
 Set the state of the first_request_ to flag. More...
 
bool first_request () const
 Get the first request flag. More...
 
void send_connection_closed_notifications (void)
 
TAO::Transport::Statsstats (void) const
 Transport statistics. More...
 
virtual TAO_Connection_Handlerconnection_handler_i (void)=0
 
int process_parsed_messages (TAO_Queued_Data *qd, TAO_Resume_Handle &rh)
 
int send_message_shared_i (TAO_Stub *stub, TAO_Message_Semantics message_semantics, const ACE_Message_Block *message_block, ACE_Time_Value *max_wait_time)
 
int queue_message_i (const ACE_Message_Block *message_block, ACE_Time_Value *max_wait_time, bool back=true)
 
ACE_Time_Value const * io_timeout (TAO::Transport::Drain_Constraints const &dc) const
 Re-factor computation of I/O timeouts based on operation timeouts. Depending on the wait strategy, we need to timeout I/O operations or not. For example, if we are using a non-blocking strategy, we want to pass 0 to all I/O operations, and rely on the ACE_NONBLOCK settings on the underlying sockets. However, for blocking strategies we want to pass the operation timeouts, to respect the application level policies. More...
 
int notify_reactor_now (void)
 
TAO::Transport_Cache_Managertransport_cache_manager (void)
 Helper method that returns the Transport Cache Manager. More...
 
Drain_Result drain_queue (TAO::Transport::Drain_Constraints const &dc)
 Send some of the data in the queue. More...
 
Drain_Result drain_queue_i (TAO::Transport::Drain_Constraints const &dc)
 Implement drain_queue() assuming the lock is held. More...
 
bool queue_is_empty_i (void) const
 Check if there are messages pending in the queue. More...
 
Drain_Result drain_queue_helper (int &iovcnt, iovec iov[], TAO::Transport::Drain_Constraints const &dc)
 A helper routine used in drain_queue_i() More...
 
int schedule_output_i (void)
 Schedule handle_output() callbacks. More...
 
int cancel_output_i (void)
 Cancel handle_output() callbacks. More...
 
void cleanup_queue (size_t byte_count)
 Cleanup the queue. More...
 
void cleanup_queue_i ()
 Cleanup the complete queue. More...
 
bool check_buffering_constraints_i (TAO_Stub *stub, bool &must_flush)
 Check if the buffering constraints have been reached. More...
 
int send_synchronous_message_i (const ACE_Message_Block *message_block, ACE_Time_Value *max_wait_time)
 
int send_reply_message_i (const ACE_Message_Block *message_block, ACE_Time_Value *max_wait_time)
 
int send_asynchronous_message_i (TAO_Stub *stub, const ACE_Message_Block *message_block, ACE_Time_Value *max_wait_time)
 
int send_synch_message_helper_i (TAO_Synch_Queued_Message &s, ACE_Time_Value *max_wait_time)
 
int flush_timer_pending (void) const
 Check if the flush timer is still pending. More...
 
void reset_flush_timer (void)
 
void report_invalid_event_handler (const char *caller)
 Print out error messages if the event handler is not valid. More...
 
int handle_input_missing_data (TAO_Resume_Handle &rh, ACE_Time_Value *max_wait_time, TAO_Queued_Data *q_data)
 
int handle_input_parse_data (TAO_Resume_Handle &rh, ACE_Time_Value *max_wait_time)
 
int handle_input_parse_extra_messages (ACE_Message_Block &message_block)
 
int consolidate_enqueue_message (TAO_Queued_Data *qd)
 
int consolidate_process_message (TAO_Queued_Data *qd, TAO_Resume_Handle &rh)
 
int process_queue_head (TAO_Resume_Handle &rh)
 
int notify_reactor (void)
 
 TAO_Transport (const TAO_Transport &)
 
TAO_Transportoperator= (const TAO_Transport &)
 
void send_connection_closed_notifications_i (void)
 Assume the lock is held. More...
 
void allocate_partial_message_block (void)
 
bool using_blocking_io_for_synch_messages () const
 
bool using_blocking_io_for_asynch_messages () const
 

Detailed Description

Generic definitions for the Transport class.

The transport object is created in the Service handler constructor and deleted in the Service Handler's destructor!!

The main responsibility of a Transport object is to encapsulate a connection, and provide a transport independent way to send and receive data. Since TAO is heavily based on the Reactor for all if not all its I/O the Transport class is usually implemented with a helper Connection Handler that adapts the generic Transport interface to the Reactor types.

The outgoing data path:

One of the responsibilities of the TAO_Transport class is to send out GIOP messages as efficiently as possible. In most cases messages are put out in FIFO order, the transport object will put out the message using a single system call and return control to the application. However, for oneways and AMI requests it may be more efficient (or required if the SYNC_NONE policy is in effect) to queue the messages until a large enough data set is available. Another reason to queue is that some applications cannot block for I/O, yet they want to send messages so large that a single write() operation would not be able to cope with them. In such cases we need to queue the data and use the Reactor to drain the queue.

Therefore, the Transport class may need to use a queue to temporarily hold the messages, and, in some configurations, it may need to use the Reactor to concurrently drain such queues.

Out of order messages:

TAO provides explicit policies to send 'urgent' messages. Such messages may put at the head of the queue. However, they cannot be sent immediately because the transport may already be sending another message in a reactive fashion.

Consequently, the Transport must also know if the head of the queue has been partially sent. In that case new messages can only follow the head. Only once the head is completely sent we can start sending new messages.

Waiting threads:

One or more threads can be blocked waiting for the connection to completely send the message. The thread should return as soon as its message has been sent, so a per-thread condition is required. This suggest that simply using a ACE_Message_Queue would not be enough: there is a significant amount of ancillary information, to keep on each message that the Message_Block class does not provide room for.

Blocking I/O is still attractive for some applications. First, my eliminating the Reactor overhead performance is improved when sending large blocks of data. Second, using the Reactor to send out data opens the door for nested upcalls, yet some applications cannot deal with the reentrancy issues in this case.

Timeouts:

Some or all messages could have a timeout period attached to them. The timeout source could either be some high-level policy or maybe some strategy to prevent denial of service attacks. In any case the timeouts are per-message, and later messages could have shorter timeouts. In fact, some kind of scheduling (such as EDF) could be required in a few applications.

Conclusions:

The outgoing data path consist in several components:

The Transport object provides a single method to send request messages (send_request_message ()).

The incoming data path:

One of the main responsibilities of the transport is to read and process the incoming GIOP message as quickly and efficiently as possible. There are other forces that needs to be given due consideration. They are

Parsing messages (GIOP) & processing the message:

The messages should be checked for validity and the right information should be sent to the higher layer for processing. The process of doing a sanity check and preparing the messages for the higher layers of the ORB are done by the messaging protocol.

Design forces and Challenges

To keep things as efficient as possible for medium sized requests, it would be good to minimize data copying and locking along the incoming path ie. from the time of reading the data from the handle to the application. We achieve this by creating a buffer on stack and reading the data from the handle into the buffer. We then pass the same data block (the buffer is encapsulated into a data block) to the higher layers of the ORB. The problems stem from the following (a) Data is bigger than the buffer that we have on stack (b) Transports like TCP do not guarantee availability of the whole chunk of data in one shot. Data could trickle in byte by byte. (c) Single read gives multiple messages

We solve the problems as follows

(a) First do a read with the buffer on stack. Query the underlying messaging object whether the message has any incomplete portion. If so, data will be copied into new buffer being able to hold full message and is queued; succeeding events will read data from socket and write directly into this buffer. Otherwise, if if the message in local buffer is complete, we free the handle and then send the message to the higher layers of the ORB for processing.

(b) If buffer with incomplete message has been enqueued, while trying to do the above, the reactor will call us back when the handle becomes read ready. The read-operation will copy data directly into the enqueued buffer. If the message has bee read completely the message is sent to the higher layers of the ORB for processing.

(c) If we get multiple messages (possible if the client connected to the server sends oneways or AMI requests), we parse and split the messages. Every message is put in the queue. Once the messages are queued, the thread picks up one message to send to the higher layers of the ORB. Before doing that, if it finds more messages, it sends a notify to the reactor without resuming the handle. The next thread picks up a message from the queue and processes that. Once the queue is drained the last thread resumes the handle.

Sending Replies

We could use the outgoing path of the ORB to send replies. This would allow us to reuse most of the code in the outgoing data path. We were doing this till TAO-1.2.3. We run in to problems. When writing the reply the ORB gets flow controlled, and the ORB tries to flush the message by going into the reactor. This resulted in unnecessary nesting. The thread that gets into the Reactor could potentially handle other messages (incoming or outgoing) and the stack starts growing leading to crashes.

Solution to the nesting problem

The solution that we (plan to) adopt is pretty straight forward. The thread sending replies will not block to send the replies but queue the replies and return to the Reactor. (Note the careful usages of the terms "blocking in the Reactor" as opposed to "return back to the Reactor".

See Also:

https://svn.dre.vanderbilt.edu/viewvc/Middleware/trunk/TAO/docs/pluggable_protocols/index.html?revision=HEAD

Member Enumeration Documentation

Enumerator
DR_ERROR 
DR_OK 
DR_QUEUE_EMPTY 
DR_WOULDBLOCK 

Constructor & Destructor Documentation

TAO_Transport::TAO_Transport ( CORBA::ULong  tag,
TAO_ORB_Core orb_core,
size_t  input_cdr_size = ACE_CDR::DEFAULT_BUFSIZE 
)

Default creator, requires the tag value be supplied.

TAO_Transport::~TAO_Transport ( void  )
virtual

Destructor.

TAO_Transport::TAO_Transport ( const TAO_Transport )
private

These classes need privileged access to:

Member Function Documentation

ACE_Event_Handler::Reference_Count TAO_Transport::add_reference ( void  )

Memory management routines.

Forwards to event handler.

void TAO_Transport::allocate_partial_message_block ( void  )
private

Allocate a partial message block and store it in our partial_message_ data member.

void TAO_Transport::assign_translators ( TAO_InputCDR inp,
TAO_OutputCDR outp 
)

Use the Transport's codeset factories to set the translator for input and output CDRs.

int TAO_Transport::bidirectional_flag ( void  ) const

Get the bidirectional flag.

void TAO_Transport::bidirectional_flag ( int  flag)

Set the bidirectional flag.

void TAO_Transport::cache_map_entry ( TAO::Transport_Cache_Manager::HASH_MAP_ENTRY entry)

Set the Cache Map entry.

TAO::Transport_Cache_Manager::HASH_MAP_ENTRY * TAO_Transport::cache_map_entry ( void  )

Get the Cache Map entry.

bool TAO_Transport::can_be_purged ( void  )

Can the transport be purged?

int TAO_Transport::cancel_output_i ( void  )
private

Cancel handle_output() callbacks.

TAO_Codeset_Translator_Base * TAO_Transport::char_translator ( void  ) const

CodeSet Negotiation - Get the char codeset translator factory.

void TAO_Transport::char_translator ( TAO_Codeset_Translator_Base tf)

CodeSet negotiation - Set the char codeset translator factory.

bool TAO_Transport::check_buffering_constraints_i ( TAO_Stub stub,
bool &  must_flush 
)
private

Check if the buffering constraints have been reached.

void TAO_Transport::cleanup_queue ( size_t  byte_count)
private

Cleanup the queue.

Exactly byte_count bytes have been sent, the queue must be cleaned up as potentially several messages have been completely sent out. It leaves on head_ the next message to send out.

void TAO_Transport::cleanup_queue_i ( )
private

Cleanup the complete queue.

void TAO_Transport::clear_translators ( TAO_InputCDR inp,
TAO_OutputCDR outp 
)

It is necessary to clear the codeset translator when a CDR stream is used for more than one GIOP message. This is required since the header must not be translated, whereas the body must be.

void TAO_Transport::close_connection ( void  )
virtual

Call the implementation method after obtaining the lock.

bool TAO_Transport::connection_closed_on_read ( void  ) const

Was a connection seen as closed during a read.

TAO_Connection_Handler * TAO_Transport::connection_handler ( void  )

Get the connection handler for this transport.

virtual TAO_Connection_Handler* TAO_Transport::connection_handler_i ( void  )
protectedpure virtual

These classes need privileged access to:

Implemented in TAO_IIOP_Transport.

int TAO_Transport::consolidate_enqueue_message ( TAO_Queued_Data qd)
private
Returns
-1 error, otherwise 0
int TAO_Transport::consolidate_process_message ( TAO_Queued_Data qd,
TAO_Resume_Handle rh 
)
private
Returns
-1 error, otherwise 0
TAO_Transport::Drain_Result TAO_Transport::drain_queue ( TAO::Transport::Drain_Constraints const &  dc)
private

Send some of the data in the queue.

As the outgoing data is drained this method is invoked to send as much of the current message as possible.

TAO_Transport::Drain_Result TAO_Transport::drain_queue_helper ( int &  iovcnt,
iovec  iov[],
TAO::Transport::Drain_Constraints const &  dc 
)
private

A helper routine used in drain_queue_i()

TAO_Transport::Drain_Result TAO_Transport::drain_queue_i ( TAO::Transport::Drain_Constraints const &  dc)
private

Implement drain_queue() assuming the lock is held.

virtual ACE_Event_Handler* TAO_Transport::event_handler_i ( void  )
pure virtual

Return the event handler used to receive notifications from the Reactor. Normally a concrete TAO_Transport object has-a ACE_Event_Handler member that functions as an adapter between the ACE_Reactor framework and the TAO pluggable protocol framework. In all the protocols implemented so far this role is fullfilled by an instance of ACE_Svc_Handler.

Todo:
Since we only use a limited functionality of ACE_Svc_Handler we could probably implement a generic adapter class (TAO_Transport_Event_Handler or something), this will reduce footprint and simplify the process of implementing a pluggable protocol.
Todo:
This method has to be renamed to event_handler()

Implemented in TAO_IIOP_Transport.

bool TAO_Transport::first_request ( void  ) const

Get the first request flag.

void TAO_Transport::first_request_sent ( bool  flag = false)

Set the state of the first_request_ to flag.

int TAO_Transport::flush_timer_pending ( void  ) const
private

Check if the flush timer is still pending.

int TAO_Transport::format_queue_message ( TAO_OutputCDR stream,
ACE_Time_Value max_wait_time,
TAO_Stub stub 
)

Format and queue a message for stream

Parameters
max_wait_timeThe maximum time that the operation can block, used in the implementation of timeouts.
int TAO_Transport::generate_locate_request ( TAO_Target_Specification spec,
TAO_Operation_Details opdetails,
TAO_OutputCDR output 
)

This is a request for the transport object to write a LocateRequest header before it is sent out.

int TAO_Transport::generate_request_header ( TAO_Operation_Details opd,
TAO_Target_Specification spec,
TAO_OutputCDR msg 
)
virtual

This is a request for the transport object to write a request header before it sends out the request

int TAO_Transport::handle_input ( TAO_Resume_Handle rh,
ACE_Time_Value max_wait_time = 0 
)
virtual

Callback to read incoming data.

The ACE_Event_Handler adapter invokes this method as part of its handle_input() operation.

Todo:
the method name is confusing! Calling it handle_input() would probably make things easier to understand and follow!

Once a complete message is read the Transport class delegates on the Messaging layer to invoke the right upcall (on the server) or the TAO_Reply_Dispatcher (on the client side).

Parameters
max_wait_timeIn some cases the I/O is synchronous, e.g. a thread-per-connection server or when Wait_On_Read is enabled. In those cases a maximum read time can be specified.

All the methods relevant to the incoming data path of the ORB are defined below

int TAO_Transport::handle_input_missing_data ( TAO_Resume_Handle rh,
ACE_Time_Value max_wait_time,
TAO_Queued_Data q_data 
)
private

Is invoked by handle_input operation. It consolidate message on top of incoming_message_stack. The amount of missing data is known and recv operation copies data directly into message buffer, as much as a single recv-invocation provides.

int TAO_Transport::handle_input_parse_data ( TAO_Resume_Handle rh,
ACE_Time_Value max_wait_time 
)
private

Is invoked by handle_input operation. It parses new messages from input stream or consolidates messages whose header has been partially read, the message size being unknown so far. It parses as much data as a single recv-invocation provides.

int TAO_Transport::handle_input_parse_extra_messages ( ACE_Message_Block message_block)
private

Is invoked by handle_input_parse_data. Parses all messages remaining in message_block.

TAO_Transport::Drain_Result TAO_Transport::handle_output ( TAO::Transport::Drain_Constraints const &  dc)

Callback method to reactively drain the outgoing data queue.

Methods called and used in the output path of the ORB.

int TAO_Transport::handle_timeout ( const ACE_Time_Value current_time,
const void *  act 
)

The timeout callback, invoked when any of the timers related to this transport expire.

Parameters
current_timeThe current time as reported from the Reactor
actThe Asynchronous Completion Token. Currently it is interpreted as follows:
  • If the ACT is the address of this->current_deadline_ the queueing timeout has expired and the queue should start flushing.
Returns
Returns 0 if there are no problems, -1 if there is an error
Todo:
In the future this function could be used to expire messages (oneways) that have been sitting for too long on the queue.

This is the only legal ACT in the current configuration....

size_t TAO_Transport::id ( void  ) const

Set and Get the identifier for this transport instance.

If not set, this will return an integer representation of the this pointer for the instance on which it's called.

void TAO_Transport::id ( size_t  id)
bool TAO_Transport::idle_after_reply ( void  )

Request is sent and the reply is received. Idle the transport now.

bool TAO_Transport::idle_after_send ( void  )

Request has been just sent, but the reply is not received. Idle the transport now.

ACE_Time_Value const * TAO_Transport::io_timeout ( TAO::Transport::Drain_Constraints const &  dc) const
protected

Re-factor computation of I/O timeouts based on operation timeouts. Depending on the wait strategy, we need to timeout I/O operations or not. For example, if we are using a non-blocking strategy, we want to pass 0 to all I/O operations, and rely on the ACE_NONBLOCK settings on the underlying sockets. However, for blocking strategies we want to pass the operation timeouts, to respect the application level policies.

This function was introduced as part of the fixes for bug 3647.

bool TAO_Transport::is_connected ( void  ) const

Is this transport really connected.

CORBA::Boolean TAO_Transport::is_tcs_set ( void  ) const

Return true if the tcs has been set.

CodeSet negotiation.

int TAO_Transport::make_idle ( void  )

Cache management.

void TAO_Transport::messaging_init ( TAO_GIOP_Message_Version const &  version)

Initializing the messaging object. This would be used by the connector side. On the acceptor side the connection handler would take care of the messaging objects.

TAO_GIOP_Message_Base * TAO_Transport::messaging_object ( void  )

Return the messaging object that is used to format the data that needs to be sent.

int TAO_Transport::notify_reactor ( void  )
private

These classes need privileged access to:

int TAO_Transport::notify_reactor_now ( void  )
protected

These classes need privileged access to:

TAO::Connection_Role TAO_Transport::opened_as ( void  ) const

Methods dealing with the role of the connection, e.g., CLIENT or SERVER. See CORBA 2.6 Specification, Section 15.5.1 for origin of definitions.

void TAO_Transport::opened_as ( TAO::Connection_Role  role)
TAO_Transport& TAO_Transport::operator= ( const TAO_Transport )
private

These classes need privileged access to:

TAO_ORB_Core * TAO_Transport::orb_core ( void  ) const

Access the ORB that owns this connection.

TAO_OutputCDR & TAO_Transport::out_stream ( void  )

Accessor for the output CDR stream.

TAO_SYNCH_MUTEX & TAO_Transport::output_cdr_lock ( void  )

Accessor for synchronizing Transport OutputCDR access.

bool TAO_Transport::post_connect_hook ( void  )
virtual

Hooks that can be overridden in concrete transports.

These hooks are invoked just after connection establishment (or after a connection is fetched from cache). The return value signifies whether the invoker should proceed with post connection establishment activities. Protocols like SSLIOP need this to verify whether connections already established have valid certificates. There are no pre_connect_hooks () since the transport doesn't exist before a connection establishment. :-)

Note
The methods are not made const with a reason.
bool TAO_Transport::post_open ( size_t  id)

Perform all the actions when this transport get opened.

void TAO_Transport::pre_close ( void  )

do what needs to be done when closing the transport

int TAO_Transport::process_parsed_messages ( TAO_Queued_Data qd,
TAO_Resume_Handle rh 
)
protected

Process the message by sending it to the higher layers of the ORB.

int TAO_Transport::process_queue_head ( TAO_Resume_Handle rh)
private

These classes need privileged access to:

bool TAO_Transport::provide_blockable_handler ( TAO::Connection_Handler_Set handlers)

Add event handlers corresponding to transports that have RW wait strategy to the handlers set. Called by the cache when the ORB is shutting down.

Parameters
handlersThe TAO_Connection_Handler_Set into which the transport should place its handler if the transport has RW strategy on.
Returns
true indicates a handler was added to the handler set. false indocates that the transport did not have a blockable handler that could be added.
void TAO_Transport::provide_handler ( TAO::Connection_Handler_Set handlers)

Added event handler to the handlers set.

Called by the cache when the cache is closing.

Parameters
handlersThe TAO_Connection_Handler_Set into which the transport should place its handler
int TAO_Transport::purge_entry ( void  )

Cache management.

unsigned long TAO_Transport::purging_order ( void  ) const

Get and Set the purging order. The purging strategy uses the set version to set the purging order.

void TAO_Transport::purging_order ( unsigned long  value)
bool TAO_Transport::queue_is_empty ( void  )

Check if there are messages pending in the queue.

Returns
true if the queue is empty
bool TAO_Transport::queue_is_empty_i ( void  ) const
private

Check if there are messages pending in the queue.

This version assumes that the lock is already held. Use with care!

Returns
true if the queue is empty
int TAO_Transport::queue_message_i ( const ACE_Message_Block message_block,
ACE_Time_Value max_wait_time,
bool  back = true 
)
protected

Queue a message for message_block

Parameters
max_wait_timeThe maximum time that the operation can block, used in the implementation of timeouts.
backIf true, the message will be pushed to the back of the queue. If false, the message will be pushed to the front of the queue.
int TAO_Transport::recache_transport ( TAO_Transport_Descriptor_Interface desc)

Recache ourselves in the cache.

Todo:

Ideally the following should be inline.

purge_entry has a return value, use it

virtual ssize_t TAO_Transport::recv ( char *  buffer,
size_t  len,
const ACE_Time_Value timeout = 0 
)
pure virtual

Read len bytes from into buf.

This method serializes on handler_lock_, guaranteeing that only thread can execute it on the same instance concurrently.

Parameters
bufferORB allocated buffer where the data should be
timeoutThe 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.

Implemented in TAO_IIOP_Transport.

size_t TAO_Transport::recv_buffer_size ( void  ) const

Accessor to recv_buffer_size_.

int TAO_Transport::register_handler ( void  )
virtual

Register the handler with the reactor.

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.
bool TAO_Transport::register_if_necessary ( void  )

Register with the reactor via the wait strategy.

int TAO_Transport::remove_handler ( void  )
virtual

Remove the handler from the reactor.

ACE_Event_Handler::Reference_Count TAO_Transport::remove_reference ( void  )

These classes need privileged access to:

void TAO_Transport::report_invalid_event_handler ( const char *  caller)
private

Print out error messages if the event handler is not valid.

void TAO_Transport::reset_flush_timer ( void  )
private

The flush timer expired or was explicitly cancelled, mark it as not pending

int TAO_Transport::schedule_output_i ( void  )
private

Schedule handle_output() callbacks.

virtual ssize_t TAO_Transport::send ( iovec *  iov,
int  iovcnt,
size_t &  bytes_transferred,
ACE_Time_Value const *  timeout 
)
pure virtual

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.

Parameters
iovcontains the data that must be sent.
timeoutis 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.
bytes_transferredshould 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 ENOENT.

Implemented in TAO_IIOP_Transport.

int TAO_Transport::send_asynchronous_message_i ( TAO_Stub stub,
const ACE_Message_Block message_block,
ACE_Time_Value max_wait_time 
)
private

Send an asynchronous message, i.e. do not block until the message is on the wire

void TAO_Transport::send_connection_closed_notifications ( void  )

Notify all the components inside a Transport when the underlying connection is closed.

void TAO_Transport::send_connection_closed_notifications_i ( void  )
private

Assume the lock is held.

virtual int TAO_Transport::send_message ( TAO_OutputCDR stream,
TAO_Stub stub = 0,
TAO_ServerRequest request = 0,
TAO_Message_Semantics  message_semantics = TAO_Message_Semantics(),
ACE_Time_Value max_time_wait = 0 
)
pure virtual

This method formats the stream and then sends the message on the transport. Once the ORB is prepared to receive a reply (see send_request() above), and all the arguments have been marshaled the CDR stream must be 'formatted', i.e. the message_size field in the GIOP header can finally be set to the proper value.

Implemented in TAO_IIOP_Transport.

int TAO_Transport::send_message_block_chain ( const ACE_Message_Block message_block,
size_t &  bytes_transferred,
ACE_Time_Value max_wait_time = 0 
)

This is a very specialized interface to send a simple chain of messages through the Transport. The only place we use this interface is in GIOP_Message_Base.cpp, to send error messages (i.e., an indication that we received a malformed GIOP message,) and to close the connection.

int TAO_Transport::send_message_block_chain_i ( const ACE_Message_Block message_block,
size_t &  bytes_transferred,
TAO::Transport::Drain_Constraints const &  dc 
)

Send a message block chain, assuming the lock is held.

int TAO_Transport::send_message_shared ( TAO_Stub stub,
TAO_Message_Semantics  message_semantics,
const ACE_Message_Block message_block,
ACE_Time_Value max_wait_time 
)
virtual

Sent the contents of message_block.

Parameters
stubThe object reference used for this operation, useful to obtain the current policies.
message_semanticsIf this is set to TAO_TWO_REQUEST this method will block until the operation is completely written on the wire. If it is set to other values this operation could return.
message_blockThe CDR encapsulation of the GIOP message that must be sent. The message may consist of multiple Message Blocks chained through the cont() field.
max_wait_timeThe maximum time that the operation can block, used in the implementation of timeouts.
int TAO_Transport::send_message_shared_i ( TAO_Stub stub,
TAO_Message_Semantics  message_semantics,
const ACE_Message_Block message_block,
ACE_Time_Value max_wait_time 
)
protected

Implement send_message_shared() assuming the handler_lock_ is held.

int TAO_Transport::send_reply_message_i ( const ACE_Message_Block message_block,
ACE_Time_Value max_wait_time 
)
private

Send a reply message, i.e. do not block until the message is on the wire, but just return after adding them to the queue.

virtual int TAO_Transport::send_request ( TAO_Stub stub,
TAO_ORB_Core orb_core,
TAO_OutputCDR stream,
TAO_Message_Semantics  message_semantics,
ACE_Time_Value max_time_wait 
)
pure virtual

Prepare the waiting and demuxing strategy to receive a reply for a new request. Preparing the ORB to receive the reply only once the request is completely sent opens the system to some subtle race conditions: suppose the ORB is running in a multi-threaded configuration, thread A makes a request while thread B is using the Reactor to process all incoming requests. Thread A could be implemented as follows: 1) send the request 2) setup the ORB to receive the reply 3) wait for the request

but in this case thread B may receive the reply between step (1) and (2), and drop it as an invalid or unexpected message. Consequently the correct implementation is: 1) setup the ORB to receive the reply 2) send the request 3) wait for the reply

The following method encapsulates this idiom.

Todo:
This is generic code, it should be factored out into the Transport class.

Implemented in TAO_IIOP_Transport.

int TAO_Transport::send_synch_message_helper_i ( TAO_Synch_Queued_Message s,
ACE_Time_Value max_wait_time 
)
private

A helper method used by send_synchronous_message_i() and send_reply_message_i(). Reusable code that could be used by both the methods.

int TAO_Transport::send_synchronous_message_i ( const ACE_Message_Block message_block,
ACE_Time_Value max_wait_time 
)
private

Send a synchronous message, i.e. block until the message is on the wire

size_t TAO_Transport::sent_byte_count ( void  ) const

Accessor to sent_byte_count_.

void TAO_Transport::set_bidir_context_info ( TAO_Operation_Details opdetails)
virtual

These classes need privileged access to:

Reimplemented in TAO_IIOP_Transport.

TAO::Transport::Stats* TAO_Transport::stats ( void  ) const

Transport statistics.

CORBA::ULong TAO_Transport::tag ( void  ) const

Return the protocol tag.

The OMG assigns unique tags (a 32-bit unsigned number) to each protocol. New protocol tags can be obtained free of charge from the OMG, check the documents in corbafwd.h for more details.

int TAO_Transport::tear_listen_point_list ( TAO_InputCDR cdr)
virtual

Extracts the list of listen points from the cdr stream. The list would have the protocol specific details of the ListenPoints

Reimplemented in TAO_IIOP_Transport.

TAO_Transport_Mux_Strategy * TAO_Transport::tms ( void  ) const

Get the TAO_Tranport_Mux_Strategy used by this object.

The role of the TAO_Transport_Mux_Strategy is described in more detail in that class' documentation. Enough is to say that the class is used to control how many threads can have pending requests over the same connection. Multiplexing multiple threads over the same connection conserves resources and is almost required for AMI, but having only one pending request per connection is more efficient and reduces the possibilities of priority inversions.

TAO::Transport_Cache_Manager & TAO_Transport::transport_cache_manager ( void  )
private

Helper method that returns the Transport Cache Manager.

int TAO_Transport::update_transport ( void  )

Cache management.

bool TAO_Transport::using_blocking_io_for_asynch_messages ( void  ) const
private

Return true if blocking I/O should be used for sending asynchronous (AMI calls, non-blocking oneways, responses to operations, etc.) messages. This is determined based on the current flushing strategy.

bool TAO_Transport::using_blocking_io_for_synch_messages ( void  ) const
private

Return true if blocking I/O should be used for sending synchronous (two-way, reliable oneways, etc.) messages. This is determined based on the current flushing and waiting strategies.

TAO_Wait_Strategy * TAO_Transport::wait_strategy ( void  ) const

Return the TAO_Wait_Strategy used by this object.

The role of the TAO_Wait_Strategy is described in more detail in that class' documentation. Enough is to say that the ORB can wait for a reply blocking on read(), using the Reactor to wait for multiple events concurrently or using the Leader/Followers protocol.

TAO_Codeset_Translator_Base * TAO_Transport::wchar_translator ( void  ) const

CodeSet Negotiation - Get the wchar codeset translator factory.

void TAO_Transport::wchar_translator ( TAO_Codeset_Translator_Base tf)

CodeSet negotiation - Set the wchar codeset translator factory.

Friends And Related Function Documentation

These classes need privileged access to:

friend class TAO_Reactive_Flushing_Strategy
friend

These classes need privileged access to:

friend class TAO_Thread_Per_Connection_Handler
friend

Needs priveleged access to event_handler_i ()

Member Data Documentation

int TAO_Transport::bidirectional_flag_
protected

Use to check if bidirectional info has been synchronized with the peer. Have we sent any info on bidirectional information or have we received any info regarding making the connection served by this transport bidirectional. The flag is used as follows:

  • We dont want to send the bidirectional context info more than once on the connection. Why? Waste of marshalling and demarshalling time on the client.
  • On the server side – once a client that has established the connection asks the server to use the connection both ways, we dont want the server to pack service info to the client. That is not allowed. We need a flag to prevent such a things from happening.

The value of this flag will be 0 if the client sends info and 1 if the server receives the info.

TAO::Transport_Cache_Manager::HASH_MAP_ENTRY* TAO_Transport::cache_map_entry_
protected

Our entry in the cache. We don't own this. It is here for our convenience. We cannot just change things around.

TAO_Codeset_Translator_Base* TAO_Transport::char_translator_
private

Additional member values required to support codeset translation.

@Phil, I think it would be nice if we could think of a way to do the following. We have been trying to use the transport for marking about translator factories and such! IMHO this is a wrong encapulation ie. trying to populate the transport object with these details. We should probably have a class something like TAO_Message_Property or TAO_Message_Translator or whatever (I am sure you get the idea) and encapsulate all these details. Coupling these seems odd. if I have to be more cynical we can move this to the connection_handler and it may more sense with the DSCP stuff around there. Do you agree?

bool TAO_Transport::connection_closed_on_read_
protected

Track if connection was seen as closed during a read so that invocation can optionally be retried using a different profile. Note that this could result in violate the "at most once" CORBA semantics.

ACE_Time_Value TAO_Transport::current_deadline_
protected

The queue will start draining no later than <queeing_deadline_> if the deadline is

bool TAO_Transport::first_request_
private

First_request_ is true until the first request is sent or received. This is necessary since codeset context information is necessary only on the first request. After that, the translators are fixed for the life of the connection.

bool TAO_Transport::flush_in_post_open_
private

Indicate that flushing needs to be done in post_open()

long TAO_Transport::flush_timer_id_
protected

The timer ID.

ACE_Lock* TAO_Transport::handler_lock_
mutableprotected

Lock that insures that activities that might use handler-related resources (such as a connection handler) get serialized. This is an ACE_Lock that gets initialized from TAO_ORB_Core::resource_factory()->create_cached_connection_lock(). 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.

TAO_Queued_Message* TAO_Transport::head_
protected

Implement the outgoing data queue.

size_t TAO_Transport::id_
protected

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.

TAO_Incoming_Message_Queue TAO_Transport::incoming_message_queue_
protected

Queue of the consolidated, incoming messages..

TAO::Incoming_Message_Stack TAO_Transport::incoming_message_stack_
protected

Stack of incoming fragments, consolidated messages are going to be enqueued in "incoming_message_queue_"

bool TAO_Transport::is_connected_
protected

Is this transport really connected or not. In case of oneways with SYNC_NONE Policy we don't wait until the connection is ready and we buffer the requests in this transport until the connection is ready

TAO_GIOP_Message_Base* TAO_Transport::messaging_object_
private

Our messaging object.

TAO::Connection_Role TAO_Transport::opening_connection_role_
protected

These classes need privileged access to:

TAO_ORB_Core* const TAO_Transport::orb_core_
protected

Global orbcore resource.

TAO_SYNCH_MUTEX TAO_Transport::output_cdr_mutex_
mutableprivate

lock for synchronizing Transport OutputCDR access

ACE_Message_Block* TAO_Transport::partial_message_
private

Holds the partial GIOP message (if there is one)

unsigned long TAO_Transport::purging_order_
protected

Used by the LRU, LFU and FIFO Connection Purging Strategies.

size_t TAO_Transport::recv_buffer_size_
protected

Size of the buffer received.

size_t TAO_Transport::sent_byte_count_
protected

Number of bytes sent.

TAO::Transport::Stats* TAO_Transport::stats_
private

Statistics.

CORBA::ULong const TAO_Transport::tag_
protected

IOP protocol tag.

TAO_Queued_Message* TAO_Transport::tail_
protected

These classes need privileged access to:

CORBA::Boolean TAO_Transport::tcs_set_
private

The tcs_set_ flag indicates that negotiation has occured and so the translators are correct, since a null translator is valid if both ends are using the same codeset, whatever that codeset might be.

TAO_Transport_Mux_Strategy* TAO_Transport::tms_
protected

Strategy to decide whether multiple requests can be sent over the same connection or the connection is exclusive for a request.

TAO_Transport_Timer TAO_Transport::transport_timer_
protected

The adapter used to receive timeout callbacks from the Reactor.

TAO_Codeset_Translator_Base* TAO_Transport::wchar_translator_
private

These classes need privileged access to:

TAO_Wait_Strategy* TAO_Transport::ws_
protected

Strategy for waiting for the reply after sending the request.


The documentation for this class was generated from the following files: