diff options
author | nanbor <nanbor@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2000-02-10 19:48:55 +0000 |
---|---|---|
committer | nanbor <nanbor@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2000-02-10 19:48:55 +0000 |
commit | 53ae527d407ebcf4cc9efb3bff2527a817da1c70 (patch) | |
tree | e7e6603e0e259db333bf25f2d8c7848e595f0231 /TAO/tao/SHMIOP_Connect.cpp | |
parent | 3b6ee8039f6c120c4290a6a01bf26dcd5032003b (diff) | |
download | ATCD-53ae527d407ebcf4cc9efb3bff2527a817da1c70.tar.gz |
ChangeLogTag:Thu Feb 10 13:25:07 2000 Nanbor Wang <nanbor@cs.wustl.edu>
Diffstat (limited to 'TAO/tao/SHMIOP_Connect.cpp')
-rw-r--r-- | TAO/tao/SHMIOP_Connect.cpp | 514 |
1 files changed, 514 insertions, 0 deletions
diff --git a/TAO/tao/SHMIOP_Connect.cpp b/TAO/tao/SHMIOP_Connect.cpp new file mode 100644 index 00000000000..24022e2c6ae --- /dev/null +++ b/TAO/tao/SHMIOP_Connect.cpp @@ -0,0 +1,514 @@ +// $Id$ + +#include "tao/SHMIOP_Connect.h" + +#if defined (TAO_HAS_SHMIOP) && (TAO_HAS_SHMIOP != 0) + +#include "tao/Timeprobe.h" +#include "tao/debug.h" +#include "tao/ORB_Core.h" +#include "tao/ORB.h" +#include "tao/CDR.h" +#include "tao/GIOP.h" + +#if !defined (__ACE_INLINE__) +# include "tao/SHMIOP_Connect.i" +#endif /* ! __ACE_INLINE__ */ + +ACE_RCSID(tao, SHMIOP_Connect, "$Id$") + +#if defined (ACE_ENABLE_TIMEPROBES) + +static const char *TAO_SHMIOP_Connect_Timeprobe_Description[] = +{ + "SHMIOP_Server_Connection_Handler::handle_input - start", + "SHMIOP_Server_Connection_Handler::handle_input - end", + + "SHMIOP_Server_Connection_Handler::handle_locate - start", + "SHMIOP_Server_Connection_Handler::handle_locate - end", + + "SHMIOP_Server_Connection_Handler::receive_request - end", + + "SHMIOP_Client_Connection_Handler::send_request - start", + "SHMIOP_Client_Connection_Handler::send_request - end"}; + +enum +{ + // Timeprobe description table start key + TAO_SHMIOP_SERVER_CONNECTION_HANDLER_HANDLE_INPUT_START = 300, + TAO_SHMIOP_SERVER_CONNECTION_HANDLER_HANDLE_INPUT_END, + + TAO_SHMIOP_SERVER_CONNECTION_HANDLER_HANDLE_LOCATE_START, + TAO_SHMIOP_SERVER_CONNECTION_HANDLER_HANDLE_LOCATE_END, + + TAO_SHMIOP_SERVER_CONNECTION_HANDLER_RECEIVE_REQUEST_END, + + TAO_SHMIOP_CLIENT_CONNECTION_HANDLER_SEND_REQUEST_START, + TAO_SHMIOP_CLIENT_CONNECTION_HANDLER_SEND_REQUEST_END +}; + +// Setup Timeprobes +ACE_TIMEPROBE_EVENT_DESCRIPTIONS (TAO_SHMIOP_Connect_Timeprobe_Description, + TAO_SHMIOP_SERVER_CONNECTION_HANDLER_HANDLE_INPUT_START); + +#endif /* ACE_ENABLE_TIMEPROBES */ + +TAO_SHMIOP_Handler_Base::TAO_SHMIOP_Handler_Base (TAO_ORB_Core *orb_core) + : TAO_SHMIOP_SVC_HANDLER (orb_core->thr_mgr (), 0, 0) +{ +} + +TAO_SHMIOP_Handler_Base::TAO_SHMIOP_Handler_Base (ACE_Thread_Manager *t) + : TAO_SHMIOP_SVC_HANDLER (t, 0, 0) +{ +} + +// **************************************************************** + +TAO_SHMIOP_Server_Connection_Handler::TAO_SHMIOP_Server_Connection_Handler (ACE_Thread_Manager *t) + : TAO_SHMIOP_Handler_Base (t), + transport_ (this, 0), + orb_core_ (0), + tss_resources_ (0), + refcount_ (1) + +{ + // This constructor should *never* get called, it is just here to + // make the compiler happy: the default implementation of the + // Creation_Strategy requires a constructor with that signature, we + // don't use that implementation, but some (most?) compilers + // instantiate it anyway. + ACE_ASSERT (this->orb_core_ != 0); +} + +TAO_SHMIOP_Server_Connection_Handler::TAO_SHMIOP_Server_Connection_Handler (TAO_ORB_Core *orb_core) + : TAO_SHMIOP_Handler_Base (orb_core), + transport_ (this, orb_core), + orb_core_ (orb_core), + tss_resources_ (orb_core->get_tss_resources ()), + refcount_ (1) +{ +} + +TAO_SHMIOP_Server_Connection_Handler::~TAO_SHMIOP_Server_Connection_Handler (void) +{ +} + +int +TAO_SHMIOP_Server_Connection_Handler::open (void*) +{ +#if !defined (ACE_LACKS_SOCKET_BUFSIZ) + int sndbufsize = + this->orb_core_->orb_params ()->sock_sndbuf_size (); + int rcvbufsize = + this->orb_core_->orb_params ()->sock_rcvbuf_size (); + + if (this->peer ().set_option (SOL_SOCKET, + SO_SNDBUF, + (void *) &sndbufsize, + sizeof (sndbufsize)) == -1 + && errno != ENOTSUP) + return -1; + else if (this->peer ().set_option (SOL_SOCKET, + SO_RCVBUF, + (void *) &rcvbufsize, + sizeof (rcvbufsize)) == -1 + && errno != ENOTSUP) + return -1; +#endif /* !ACE_LACKS_SOCKET_BUFSIZ */ + +#if defined (TCP_NODELAY) + int nodelay = + this->orb_core_->orb_params ()->nodelay (); + + if (this->peer ().set_option (ACE_IPPROTO_TCP, + TCP_NODELAY, + (void *) &nodelay, + sizeof (nodelay)) == -1) + return -1; +#endif /* TCP_NODELAY */ + + (void) this->peer ().enable (ACE_CLOEXEC); + // Set the close-on-exec flag for that file descriptor. If the + // operation fails we are out of luck (some platforms do not support + // it and return -1). + + // Called by the <Strategy_Acceptor> when the handler is completely + // connected. + ACE_INET_Addr addr; + + if (this->peer ().get_remote_addr (addr) == -1) + return -1; + + char client[MAXHOSTNAMELEN + 16]; + (void) addr.addr_to_string (client, sizeof (client)); + + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG, + ASYS_TEXT ("TAO (%P|%t) SHMIOP connection from client <%s> on %d\n"), + client, this->peer ().get_handle ())); + + return 0; +} + +int +TAO_SHMIOP_Server_Connection_Handler::activate (long flags, + int n_threads, + int force_active, + long priority, + int grp_id, + ACE_Task_Base *task, + ACE_hthread_t thread_handles[], + void *stack[], + size_t stack_size[], + ACE_thread_t thread_names[]) +{ + if (TAO_orbdebug) + ACE_DEBUG ((LM_DEBUG, + ASYS_TEXT ("TAO (%P|%t) SHMIOP_Server_Connection_Handler::activate %d ") + ASYS_TEXT ("threads, flags = %d\n"), + n_threads, + flags, + THR_BOUND)); + + return TAO_SHMIOP_SVC_HANDLER::activate (flags, + n_threads, + force_active, + priority, + grp_id, + task, + thread_handles, + stack, + stack_size, + thread_names); +} + +int +TAO_SHMIOP_Server_Connection_Handler::handle_close (ACE_HANDLE handle, + ACE_Reactor_Mask rm) +{ + if (TAO_orbdebug) + ACE_DEBUG ((LM_DEBUG, + ASYS_TEXT ("TAO (%P|%t) SHMIOP_Server_Connection_Handler::handle_close ") + ASYS_TEXT ("(%d, %d)\n"), + handle, + rm)); + + --this->refcount_; + if (this->refcount_ == 0) + { + this->peer().remove (); + return TAO_SHMIOP_SVC_HANDLER::handle_close (handle, rm); + } + + return 0; +} + +int +TAO_SHMIOP_Server_Connection_Handler::svc (void) +{ + // This method is called when an instance is "activated", i.e., + // turned into an active object. Presumably, activation spawns a + // thread with this method as the "worker function". + int result = 0; + + // Inheriting the ORB_Core tss stuff from the parent thread. + this->orb_core_->inherit_from_parent_thread (this->tss_resources_); + + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG, + ASYS_TEXT ("TAO (%P|%t) SHMIOP_Server_Connection_Handler::svc begin\n"))); + + // Here we simply synthesize the "typical" event loop one might find + // in a reactive handler, except that this can simply block waiting + // for input. + + ACE_Time_Value *max_wait_time = 0; + ACE_Time_Value timeout; + ACE_Time_Value current_timeout; + if (this->orb_core_->thread_per_connection_timeout (timeout)) + { + current_timeout = timeout; + max_wait_time = ¤t_timeout; + } + + while (!this->orb_core_->has_shutdown () + && result >= 0) + { + result = handle_input_i (ACE_INVALID_HANDLE, max_wait_time); + if (result == -1 && errno == ETIME) + { + // Ignore timeouts, they are only used to wake up and + // shutdown. + result = 0; + } + current_timeout = timeout; + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG, + ASYS_TEXT ("TAO (%P|%t) SHMIOP_Server_Connection_Handler::svc - ") + ASYS_TEXT ("loop <%d>\n"), current_timeout.msec ())); + } + + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG, + ASYS_TEXT ("TAO (%P|%t) SHMIOP_Server_Connection_Handler::svc end\n"))); + + return result; +} + +int +TAO_SHMIOP_Server_Connection_Handler::handle_input (ACE_HANDLE h) +{ + return this->handle_input_i (h); +} + +int +TAO_SHMIOP_Server_Connection_Handler::handle_input_i (ACE_HANDLE, + ACE_Time_Value *max_wait_time) +{ + this->refcount_++; + + int result = TAO_GIOP::handle_input (this->transport (), + this->orb_core_, + this->transport_.message_state_, + max_wait_time); + + if (result == -1 && TAO_debug_level > 0) + { + ACE_DEBUG ((LM_DEBUG, + ASYS_TEXT ("TAO (%P|%t) - %p\n"), + ASYS_TEXT ("SHMIOP_Server_Connection_Handler::handle_input, ") + ASYS_TEXT ("handle_input"))); + } + + if (result == 0 || result == -1) + { + --this->refcount_; + if (this->refcount_ == 0) + this->TAO_SHMIOP_SVC_HANDLER::handle_close (); + return result; + } + + // + // Take out all the information from the <message_state> and reset + // it so that nested upcall on the same transport can be handled. + // + + // Notice that the message_state is only modified in one thread at a + // time because the reactor does not call handle_input() for the + // same Event_Handler in two threads at the same time. + + // Copy message type. + TAO_GIOP_Message_State &ms = this->transport_.message_state_; + CORBA::Octet message_type = ms.message_type; + + // Copy version. + TAO_GIOP_Version giop_version = ms.giop_version; + + // Steal the input CDR from the message state. + TAO_InputCDR input_cdr (ACE_InputCDR::Transfer_Contents (ms.cdr), + this->orb_core_); + + // Reset the message state. + this->transport_.message_state_.reset (0); + + result = TAO_GIOP::process_server_message (this->transport (), + this->orb_core_, + input_cdr, + message_type, + giop_version); + if (result != -1) + result = 0; + + --this->refcount_; + if (this->refcount_ == 0) + this->TAO_SHMIOP_SVC_HANDLER::handle_close (); + + return result; +} + +// **************************************************************** + +// transport obj. +TAO_SHMIOP_Client_Connection_Handler:: +TAO_SHMIOP_Client_Connection_Handler (ACE_Thread_Manager *t, + TAO_ORB_Core* orb_core) + : TAO_SHMIOP_Handler_Base (t), + transport_ (this, orb_core), + orb_core_ (orb_core) +{ +} + +TAO_SHMIOP_Client_Connection_Handler::~TAO_SHMIOP_Client_Connection_Handler (void) +{ +} + +int +TAO_SHMIOP_Client_Connection_Handler::open (void *) +{ + // @@ TODO: This flags should be set using the RT CORBA policies... + + // Here is where we could enable all sorts of things such as + // nonblock I/O, sock buf sizes, TCP no-delay, etc. + +#if !defined (ACE_LACKS_SOCKET_BUFSIZ) + int sndbufsize = + this->orb_core_->orb_params ()->sock_sndbuf_size (); + int rcvbufsize = + this->orb_core_->orb_params ()->sock_rcvbuf_size (); + + if (this->peer ().set_option (SOL_SOCKET, + SO_SNDBUF, + ACE_reinterpret_cast (void *, &sndbufsize), + sizeof (sndbufsize)) == -1 + && errno != ENOTSUP) + return -1; + else if (this->peer ().set_option (SOL_SOCKET, + SO_RCVBUF, + ACE_reinterpret_cast (void *, &rcvbufsize), + sizeof (rcvbufsize)) == -1 + && errno != ENOTSUP) + return -1; +#endif /* ACE_LACKS_SOCKET_BUFSIZ */ + +#if defined (TCP_NODELAY) + int nodelay = + this->orb_core_->orb_params ()->nodelay (); + if (this->peer ().set_option (ACE_IPPROTO_TCP, + TCP_NODELAY, + (void *) &nodelay, + sizeof (nodelay)) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + ASYS_TEXT ("NODELAY failed\n")), + -1); +#endif /* TCP_NODELAY */ + + (void) this->peer ().enable (ACE_CLOEXEC); + // Set the close-on-exec flag for that file descriptor. If the + // operation fails we are out of luck (some platforms do not support + // it and return -1). + + // Called by the <Strategy_Acceptor> when the handler is completely + // connected. + ACE_INET_Addr addr; + + if (this->peer ().get_remote_addr (addr) == -1) + return -1; + + char server[MAXHOSTNAMELEN + 16]; + + (void) addr.addr_to_string (server, sizeof (server)); + + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG, + ASYS_TEXT ("TAO (%P|%t) SHMIOP connection to server <%s> on %d\n"), + server, this->peer ().get_handle ())); + + // Register the handler with the Reactor if necessary. + return this->transport ()->wait_strategy ()->register_handler (); +} + +int +TAO_SHMIOP_Client_Connection_Handler::close (u_long) +{ + this->destroy (); + + return 0; +} + +int +TAO_SHMIOP_Client_Connection_Handler::handle_input (ACE_HANDLE) +{ + // Call the waiter to handle the input. + return this->transport ()->wait_strategy ()->handle_input (); +} + +int +TAO_SHMIOP_Client_Connection_Handler::handle_timeout (const ACE_Time_Value &, + const void *) +{ + // + // This method is called when buffering timer expires. + // + + // Cannot deal with errors, and therefore they are ignored. + this->transport ()->send_buffered_messages (); + + return 0; +} + +int +TAO_SHMIOP_Client_Connection_Handler::handle_close (ACE_HANDLE handle, + ACE_Reactor_Mask rm) +{ + // @@ Alex: we need to figure out if the transport decides to close + // us or something else. If it is something else (for example + // the cached connector trying to make room for other + // connections) then we should let the transport know, so it can + // in turn take appropiate action (such as sending exceptions to + // all waiting reply handlers). + + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG, + ASYS_TEXT ("TAO (%P|%t) SHMIOP_Client_Connection_Handler::") + ASYS_TEXT ("handle_close (%d, %d)\n"), handle, rm)); + + if (this->recycler ()) + this->recycler ()->mark_as_closed (this->recycling_act ()); + + // Deregister this handler with the ACE_Reactor. + return this->handle_cleanup (); +} + +int +TAO_SHMIOP_Client_Connection_Handler::handle_close_i (ACE_HANDLE handle, + ACE_Reactor_Mask rm) +{ + // @@ Alex: we need to figure out if the transport decides to close + // us or something else. If it is something else (for example + // the cached connector trying to make room for other + // connections) then we should let the transport know, so it can + // in turn take appropiate action (such as sending exceptions to + // all waiting reply handlers). + + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG, + ASYS_TEXT ("TAO (%P|%t) SHMIOP_Client_Connection_Handler::") + ASYS_TEXT ("handle_close_i (%d, %d)\n"), handle, rm)); + + if (this->recycler ()) + this->recycler ()->mark_as_closed_i (this->recycling_act ()); + + return this->handle_cleanup (); +} + +int +TAO_SHMIOP_Client_Connection_Handler::handle_cleanup (void) +{ + // Deregister this handler with the ACE_Reactor. + if (this->reactor ()) + { + ACE_Reactor_Mask mask = + ACE_Event_Handler::ALL_EVENTS_MASK | ACE_Event_Handler::DONT_CALL; + + // Make sure there are no timers. + this->reactor ()->cancel_timer (this); + + // Remove self from reactor. + this->reactor ()->remove_handler (this, mask); + } + + this->peer ().close (); + + return 0; +} + +// **************************************************************** + +#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) + +#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) + +#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ + +#endif /* TAO_HAS_SHMIOP && TAO_HAS_SHMIOP != 0 */ |