summaryrefslogtreecommitdiff
path: root/TAO/tao/Transport.h
diff options
context:
space:
mode:
authorWilliam R. Otte <wotte@dre.vanderbilt.edu>2006-07-24 15:50:11 +0000
committerWilliam R. Otte <wotte@dre.vanderbilt.edu>2006-07-24 15:50:11 +0000
commit6b846cf03c0bcbd8c276cb0af61a181e5f98eaae (patch)
treeda50d054f9c761c3f6a5923f6979e93306c56d68 /TAO/tao/Transport.h
parent0e555b9150d38e3b3473ba325b56db2642e6352b (diff)
downloadATCD-6b846cf03c0bcbd8c276cb0af61a181e5f98eaae.tar.gz
Repo restructuring
Diffstat (limited to 'TAO/tao/Transport.h')
-rw-r--r--TAO/tao/Transport.h1082
1 files changed, 0 insertions, 1082 deletions
diff --git a/TAO/tao/Transport.h b/TAO/tao/Transport.h
deleted file mode 100644
index 18d8ca2d89b..00000000000
--- a/TAO/tao/Transport.h
+++ /dev/null
@@ -1,1082 +0,0 @@
-// -*- C++ -*-
-
-//=============================================================================
-/**
- * @file Transport.h
- *
- * $Id$
- *
- * Define the interface for the Transport component in TAO's
- * pluggable protocol framework.
- *
- * @author Fred Kuhns <fredk@cs.wustl.edu>
- */
-//=============================================================================
-
-#ifndef TAO_TRANSPORT_H
-#define TAO_TRANSPORT_H
-
-#include /**/ "ace/pre.h"
-
-#include "tao/Transport_Cache_Manager.h"
-
-#if !defined (ACE_LACKS_PRAGMA_ONCE)
-# pragma once
-#endif /* ACE_LACKS_PRAGMA_ONCE */
-
-#include "tao/Transport_Timer.h"
-#include "tao/Incoming_Message_Queue.h"
-#include "tao/Incoming_Message_Stack.h"
-#include "ace/Time_Value.h"
-
-struct iovec;
-
-TAO_BEGIN_VERSIONED_NAMESPACE_DECL
-
-class TAO_ORB_Core;
-class TAO_Target_Specification;
-class TAO_Operation_Details;
-class TAO_Transport_Mux_Strategy;
-class TAO_Wait_Strategy;
-class TAO_Connection_Handler;
-class TAO_Pluggable_Messaging;
-class TAO_Codeset_Translator_Base;
-
-class TAO_Queued_Message;
-class TAO_Synch_Queued_Message;
-class TAO_Resume_Handle;
-class TAO_Stub;
-class TAO_MMAP_Allocator;
-
-namespace TAO
-{
- /**
- * @note Should this be in TAO namespace. Seems like a candidate
- * that should be in the transport
- */
- enum Connection_Role
- {
- TAO_UNSPECIFIED_ROLE = 0,
- TAO_SERVER_ROLE = 1,
- TAO_CLIENT_ROLE = 2
- };
-}
-
-/*
- * Specialization hook for the TAO's transport implementation.
- */
-//@@ TAO_TRANSPORT_SPL_INCLUDE_FORWARD_DECL_ADD_HOOK
-
-/**
- * @class TAO_Transport
- *
- * @brief 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 responsability 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.
- *
- * <H3>The outgoing data path:</H3>
- *
- * 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.
- *
- * <H4>Out of order messages:</H4> 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.
- *
- * <H4>Waiting threads:</H4> 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.
- *
- * <H4>Timeouts:</H4> 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.
- *
- * <H4>Conclusions:</H4> The outgoing data path consist in several
- * components:
- *
- * - A queue of pending messages
- * - A message currently being transmitted
- * - A per-transport 'send strategy' to choose between blocking on
- * write, blocking on the reactor or blockin on leader/follower.
- * - A per-message 'waiting object'
- * - A per-message timeout
- *
- * The Transport object provides a single method to send request
- * messages (send_request_message ()).
- *
- * <H3>The incoming data path:</H3>
- *
- * 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
- * - Multiple threads should be able to traverse along the same data
- * path but should not be able to read from the same handle at the
- * same time ie. the handle should not be shared between threads at
- * any instant.
- * - Reads on the handle could give one or more messages.
- * - Minimise locking and copying overhead when trying to attack the
- * above.
- *
- * <H3> Parsing messages (GIOP) & processing the message:</H3>
- *
- * 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.
- *
- * <H3> Design forces and Challenges </H3>
- *
- * To keep things as efficient as possible for medium sized requests,
- * it would be good to minimise 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.
- *
- * <H3> Sending Replies </H3>
- *
- * 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.
- *
- * <H4> Solution to the nesting problem </H4>
- *
- * 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".
- *
- *
- * <B>See Also:</B>
- *
- * http://cvs.doc.wustl.edu/ace-latest.cgi/ACE_wrappers/TAO/docs/pluggable_protocols/index.html
- *
- */
-class TAO_Export TAO_Transport
-{
-public:
-
- /// Default creator, requires the tag value be supplied.
- TAO_Transport (CORBA::ULong tag,
- TAO_ORB_Core *orb_core);
-
- /// Destructor
- virtual ~TAO_Transport (void);
-
- /// 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.
- */
- CORBA::ULong tag (void) const;
-
- /// Access the ORB that owns this connection.
- TAO_ORB_Core *orb_core (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_Mux_Strategy *tms (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_Wait_Strategy *wait_strategy (void) const;
-
- /// Callback method to reactively drain the outgoing data queue
- int handle_output (void);
-
- /// Get the bidirectional flag
- int bidirectional_flag (void) const;
-
- /// Set the bidirectional flag
- void bidirectional_flag (int flag);
-
- /// Set the Cache Map entry
- void cache_map_entry (TAO::Transport_Cache_Manager::HASH_MAP_ENTRY *entry);
-
- /// Get the Cache Map entry
- TAO::Transport_Cache_Manager::HASH_MAP_ENTRY *cache_map_entry (void);
-
- /// Set and Get the identifier for this transport instance.
- /**
- * If not set, this will return an integer representation of
- * the <code>this</code> pointer for the instance on which
- * it's called.
- */
- size_t id (void) const;
- void id (size_t id);
-
- /**
- * 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.
- */
- TAO::Connection_Role opened_as (void) const;
- void opened_as (TAO::Connection_Role);
-
- /// Get and Set the purging order. The purging strategy uses the set
- /// version to set the purging order.
- unsigned long purging_order (void) const;
- void purging_order(unsigned long value);
-
- /// Check if there are messages pending in the queue
- /**
- * @return 1 if the queue is empty
- */
- int queue_is_empty (void);
-
- /// Added event handler to the handlers set.
- /**
- * Called by the cache when the cache is closing.
- *
- * @param handlers The TAO_Connection_Handler_Set into which the
- * transport should place its handler
- */
- void provide_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 shuting down.
- *
- * @param handlers The TAO_Connection_Handler_Set into which the
- * transport should place its handler if the transport has RW
- * strategy on.
- *
- * @return 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.
- */
- bool provide_blockable_handler (TAO::Connection_Handler_Set &handlers);
-
- /// 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.
- */
- virtual int register_handler (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 iov contains the data that must be sent.
- *
- * @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>.
- */
- virtual ssize_t send (iovec *iov,
- int iovcnt,
- size_t &bytes_transferred,
- const ACE_Time_Value *timeout = 0) = 0;
-
-#ifdef ACE_HAS_SENDFILE
- /// Send data through zero-copy write mechanism, if available.
- /**
- * This method sends the data in the I/O vector through the platform
- * sendfile() function to perform a zero-copy write, if available.
- * Otherwise, the default fallback implementation simply delegates
- * to the TAO_Transport::send() method.
- *
- * @note This method is best used when sending very large blocks of
- * data.
- */
- virtual ssize_t sendfile (TAO_MMAP_Allocator * allocator,
- iovec * iov,
- int iovcnt,
- size_t &bytes_transferred,
- ACE_Time_Value const * timeout = 0);
-#endif /* ACE_HAS_SENDFILE */
-
-
- /// 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.
- */
- virtual ssize_t recv (char *buffer,
- size_t len,
- const ACE_Time_Value *timeout = 0) = 0;
-
- /**
- * @name Control connection lifecycle
- *
- * These methods are routed through the TMS object. The TMS
- * strategies implement them correctly.
- */
- //@{
-
- /// Request has been just sent, but the reply is not received. Idle
- /// the transport now.
- bool idle_after_send (void);
-
- /// Request is sent and the reply is received. Idle the transport
- /// now.
- bool idle_after_reply (void);
-
- /// Call the implementation method after obtaining the lock.
- virtual void close_connection (void);
-
- //@}
-
- /** @name 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.
- */
- /**
- * Initialising 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.
- */
- virtual int messaging_init (CORBA::Octet major,
- CORBA::Octet minor) = 0;
-
- /// Extracts the list of listen points from the @a cdr stream. The
- /// list would have the protocol specific details of the
- /// ListenPoints
- virtual int tear_listen_point_list (TAO_InputCDR &cdr);
-
- /// 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.
- */
- virtual bool post_connect_hook (void);
-
- /// Memory management routines.
- /*
- * Forwards to event handler.
- */
- ACE_Event_Handler::Reference_Count add_reference (void);
- ACE_Event_Handler::Reference_Count remove_reference (void);
-
- /// Return the messaging object that is used to format the data that
- /// needs to be sent.
- virtual TAO_Pluggable_Messaging * messaging_object (void) = 0;
-
- /** @name 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.
- */
- //@{
-
- /// 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()
- */
- virtual ACE_Event_Handler * event_handler_i (void) = 0;
-
- /// Is this transport really connected
- bool is_connected (void) const;
-
- /// Perform all the actions when this transport get opened
- bool post_open (size_t id);
-
- /// Get the connection handler for this transport
- TAO_Connection_Handler * connection_handler (void);
-
- /// Accessor for the output CDR stream
- TAO_OutputCDR &out_stream (void);
-
- /*
- * Specialization hook to add public methods from
- * concrete transport implementations to TAO's transport
- * class
- */
- //@@ TAO_TRANSPORT_SPL_PUBLIC_METHODS_ADD_HOOK
-
-protected:
-
- virtual TAO_Connection_Handler * connection_handler_i (void) = 0;
-
-public:
-
- /// This is a request for the transport object to write a
- /// LocateRequest header before it is sent out.
- int 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 request
- /// header before it sends out the request
- virtual int generate_request_header (TAO_Operation_Details &opd,
- TAO_Target_Specification &spec,
- TAO_OutputCDR &msg);
-
- /// Recache ourselves in the cache
- int recache_transport (TAO_Transport_Descriptor_Interface* desc);
-
- /// 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).
- *
- * @param max_wait_time In 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.
- *
- * @param block Is deprecated and ignored.
- *
- */
- virtual int handle_input (TAO_Resume_Handle &rh,
- ACE_Time_Value *max_wait_time = 0,
- int block = 0);
-
- enum
- {
- TAO_ONEWAY_REQUEST = 0,
- TAO_TWOWAY_REQUEST = 1,
- TAO_REPLY
- };
-
- /// 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.
- */
- // @nolock b/c this calls send_or_buffer
- virtual int send_request (TAO_Stub *stub,
- TAO_ORB_Core *orb_core,
- TAO_OutputCDR &stream,
- int message_semantics,
- ACE_Time_Value *max_time_wait) = 0;
-
-
-
- /// 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.
- *
- */
- virtual int send_message (TAO_OutputCDR &stream,
- TAO_Stub *stub = 0,
- int message_semantics = TAO_Transport::TAO_TWOWAY_REQUEST,
- ACE_Time_Value *max_time_wait = 0) = 0;
-
-
- /// Sent the contents of @a message_block
- /**
- * @param stub The object reference used for this operation, useful
- * to obtain the current policies.
- * @param message_semantics If 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.
- * @param message_block The CDR encapsulation of the GIOP message
- * that must be sent. The message may consist of
- * multiple Message Blocks chained through the cont()
- * field.
- * @param max_wait_time The maximum time that the operation can
- * 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);
-
-protected:
-
- /// Process the message by sending it to the higher layers of the
- /// ORB.
- int process_parsed_messages (TAO_Queued_Data *qd,
- TAO_Resume_Handle &rh);
-
- /// Implement send_message_shared() assuming the handler_lock_ is
- /// held.
- int send_message_shared_i (TAO_Stub *stub,
- int message_semantics,
- const ACE_Message_Block *message_block,
- ACE_Time_Value *max_wait_time);
-
- /// Queue a message for @a message_block
- int queue_message_i (const ACE_Message_Block *message_block);
-
-public:
- /// Format and queue a message for @a stream
- int format_queue_message (TAO_OutputCDR &stream);
-
- /// Send a message block chain,
- int send_message_block_chain (const ACE_Message_Block *message_block,
- size_t &bytes_transferred,
- ACE_Time_Value *max_wait_time = 0);
-
- /// Send a message block chain, assuming the lock is held
- int send_message_block_chain_i (const ACE_Message_Block *message_block,
- size_t &bytes_transferred,
- ACE_Time_Value *max_wait_time);
- /// Cache management
- int purge_entry (void);
-
- /// 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.
- /**
- * @param current_time The current time as reported from the Reactor
- * @param act The 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.
- *
- * @return 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.
- */
- int handle_timeout (const ACE_Time_Value &current_time,
- const void* act);
-
- /// Accessor to recv_buffer_size_
- size_t recv_buffer_size (void) const;
-
- /// Accessor to sent_byte_count_
- size_t sent_byte_count (void) const;
-
- /// CodeSet Negotiation - Get the char codeset translator factory
- TAO_Codeset_Translator_Base *char_translator (void) const;
-
- /// CodeSet Negotiation - Get the wchar codeset translator factory
- TAO_Codeset_Translator_Base *wchar_translator (void) const;
-
- /// CodeSet negotiation - Set the char codeset translator factory
- void char_translator (TAO_Codeset_Translator_Base *);
-
- /// CodeSet negotiation - Set the wchar codeset translator factory
- void wchar_translator (TAO_Codeset_Translator_Base *);
-
- /// Use the Transport's codeset factories to set the translator for input
- /// and output CDRs.
- void assign_translators (TAO_InputCDR *, TAO_OutputCDR *);
-
- /// 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 clear_translators (TAO_InputCDR *, TAO_OutputCDR *);
-
- /// Return true if the tcs has been set
- CORBA::Boolean is_tcs_set() const;
-
- /// Set the state of the first_request_ flag to 0
- void first_request_sent();
-
- /// Notify all the components inside a Transport when the underlying
- /// connection is closed.
- void send_connection_closed_notifications (void);
-
-private:
-
- /// Helper method that returns the Transport Cache Manager.
- TAO::Transport_Cache_Manager &transport_cache_manager (void);
-
- /// 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.
- *
- * Returns 0 if there is more data to send, -1 if there was an error
- * and 1 if the message was completely sent.
- */
- int drain_queue (void);
-
- /// Implement drain_queue() assuming the lock is held
- int drain_queue_i (void);
-
- /// This class needs priviledged access to
- /// - queue_is_empty_i()
- /// - drain_queue_i()
- friend class TAO_Block_Flushing_Strategy;
-
- /// Check if there are messages pending in the queue
- /**
- * This version assumes that the lock is already held. Use with
- * care!
- *
- * @return 1 if the queue is empty
- */
- int queue_is_empty_i (void);
-
- /// A helper routine used in drain_queue_i()
- int drain_queue_helper (int &iovcnt, iovec iov[]);
-
- /// These classes need privileged access to:
- /// - schedule_output_i()
- /// - cancel_output_i()
- friend class TAO_Reactive_Flushing_Strategy;
- friend class TAO_Leader_Follower_Flushing_Strategy;
-
- /// Needs priveleged access to
- /// event_handler_i ()
- friend class TAO_Thread_Per_Connection_Handler;
-
- /// Schedule handle_output() callbacks
- int schedule_output_i (void);
-
- /// Cancel handle_output() callbacks
- int cancel_output_i (void);
-
- /// Cleanup the queue.
- /**
- * Exactly @a 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 cleanup_queue (size_t byte_count);
-
- /// Cleanup the complete queue
- void cleanup_queue_i ();
-
- /// Check if the buffering constraints have been reached
- int check_buffering_constraints_i (TAO_Stub *stub, bool &must_flush);
-
- /// Send a synchronous message, i.e. block until the message is on
- /// the wire
- int send_synchronous_message_i (const ACE_Message_Block *message_block,
- ACE_Time_Value *max_wait_time);
-
- /// 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.
- int send_reply_message_i (const ACE_Message_Block *message_block,
- ACE_Time_Value *max_wait_time);
-
- /// Send an asynchronous message, i.e. do not block until the message is on
- /// the wire
- int send_asynchronous_message_i (TAO_Stub *stub,
- const ACE_Message_Block *message_block,
- ACE_Time_Value *max_wait_time);
-
- /// 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 send_synch_message_helper_i (TAO_Synch_Queued_Message &s,
- ACE_Time_Value *max_wait_time);
-
- /// Check if the flush timer is still pending
- int flush_timer_pending (void) const;
-
- /// The flush timer expired or was explicitly cancelled, mark it as
- /// not pending
- void reset_flush_timer (void);
-
- /// Print out error messages if the event handler is not valid
- void report_invalid_event_handler (const char *caller);
-
- /// 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 handle_input_missing_data (TAO_Resume_Handle &rh,
- ACE_Time_Value *max_wait_time,
- TAO_Queued_Data *q_data);
-
- /// 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 handle_input_parse_data (TAO_Resume_Handle &rh,
- ACE_Time_Value *max_wait_time);
-
- /// Is invoked by handle_input_parse_data. Parses all messages remaining
- /// in @a message_block.
- int handle_input_parse_extra_messages (ACE_Message_Block &message_block);
-
- /// @return -1 error, otherwise 0
- int consolidate_enqueue_message (TAO_Queued_Data *qd);
-
- /// @return -1 error, otherwise 0
- int consolidate_process_message (TAO_Queued_Data *qd, TAO_Resume_Handle &rh);
-
- /*
- * Process the message that is in the head of the incoming queue.
- * If there are more messages in the queue, this method calls
- * this->notify_reactor () to wake up a thread
- * @retval -1 on error
- * @retval 0 if successfully processing enqueued messages
- * @retval 1 if no message present in queue
- */
- int process_queue_head (TAO_Resume_Handle &rh);
-
- /*
- * This call prepares a new handler for the notify call and sends a
- * notify () call to the reactor.
- */
- int notify_reactor (void);
-
- /// Assume the lock is held
- void send_connection_closed_notifications_i (void);
-
- /// Allocate a partial message block and store it in our
- /// partial_message_ data member.
- void allocate_partial_message_block (void);
-
- // Disallow copying and assignment.
- TAO_Transport (const TAO_Transport&);
- void operator= (const TAO_Transport&);
-
- /*
- * Specialization hook to add concrete private methods from
- * TAO's protocol implementation onto the base Transport class
- */
-
- //@@ TAO_TRANSPORT_SPL_PRIVATE_METHODS_ADD_HOOK
-
-protected:
-
- /// IOP protocol tag.
- CORBA::ULong const tag_;
-
- /// Global orbcore resource.
- TAO_ORB_Core * const orb_core_;
-
- /// Our entry in the cache. We don't own this. It is here for our
- /// convenience. We cannot just change things around.
- TAO::Transport_Cache_Manager::HASH_MAP_ENTRY *cache_map_entry_;
-
- /// Strategy to decide whether multiple requests can be sent over the
- /// same connection or the connection is exclusive for a request.
- TAO_Transport_Mux_Strategy *tms_;
-
- /// Strategy for waiting for the reply after sending the request.
- TAO_Wait_Strategy *ws_;
-
- /// 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.
- */
- int bidirectional_flag_;
-
- TAO::Connection_Role opening_connection_role_;
-
- /// Implement the outgoing data queue
- TAO_Queued_Message *head_;
- TAO_Queued_Message *tail_;
-
- /// Queue of the consolidated, incoming messages..
- TAO_Incoming_Message_Queue incoming_message_queue_;
-
- /// Stack of incoming fragments, consolidated messages
- /// are going to be enqueued in "incoming_message_queue_"
- TAO::Incoming_Message_Stack incoming_message_stack_;
-
- /// The queue will start draining no later than <queeing_deadline_>
- /// *if* the deadline is
- ACE_Time_Value current_deadline_;
-
- /// The timer ID
- long flush_timer_id_;
-
- /// The adapter used to receive timeout callbacks from the Reactor
- TAO_Transport_Timer transport_timer_;
-
- /// 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
- * @c 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.
- */
- mutable 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.
- */
- size_t id_;
-
- /// Used by the LRU, LFU and FIFO Connection Purging Strategies.
- unsigned long purging_order_;
-
- /// Size of the buffer received.
- size_t recv_buffer_size_;
-
- /// Number of bytes sent.
- size_t sent_byte_count_;
-
- /// 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
- bool is_connected_;
-
-private:
-
- /// @@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?
-
- /// Additional member values required to support codeset translation
- TAO_Codeset_Translator_Base *char_translator_;
- TAO_Codeset_Translator_Base *wchar_translator_;
-
- /// 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.
- CORBA::Boolean tcs_set_;
-
- /// 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.
- CORBA::Boolean first_request_;
-
- /// Holds the partial GIOP message (if there is one)
- ACE_Message_Block* partial_message_;
-
-#ifdef ACE_HAS_SENDFILE
- /// mmap()-based allocator used to allocator output CDR buffers.
- /**
- * If this pointer is non-zero, sendfile() will be used to send data
- * in a TAO_OutputCDR stream instance.
- */
- TAO_MMAP_Allocator * const mmap_allocator_;
-#endif /* ACE_HAS_SENDFILE */
-
- /*
- * specialization hook to add class members from concrete
- * transport class onto the base transport class. Please
- * add any private members to this class *before* this hook.
- */
- //@@ TAO_TRANSPORT_SPL_DATA_MEMBERS_ADD_HOOK
-};
-
-/*
- * Hook to add external typedefs and specializations to
- * TAO's transport implementation.
- */
-
-//@@ TAO_TRANSPORT_SPL_EXTERN_ADD_HOOK
-
-TAO_END_VERSIONED_NAMESPACE_DECL
-
-#if defined (__ACE_INLINE__)
-# include "tao/Transport.inl"
-#endif /* __ACE_INLINE__ */
-
-#include /**/ "ace/post.h"
-
-#endif /* TAO_TRANSPORT_H */