Connection_Handler.cpp

Go to the documentation of this file.
00001 //$Id: Connection_Handler.cpp 80603 2008-02-11 22:14:39Z johnc $
00002 
00003 #include "tao/Connection_Handler.h"
00004 #include "tao/ORB_Core.h"
00005 #include "tao/debug.h"
00006 #include "tao/Resume_Handle.h"
00007 #include "tao/Transport.h"
00008 #include "tao/Wait_Strategy.h"
00009 
00010 #include "ace/SOCK.h"
00011 #include "ace/Reactor.h"
00012 #include "ace/os_include/sys/os_socket.h"
00013 
00014 //@@ CONNECTION_HANDLER_SPL_INCLUDE_FORWARD_DECL_ADD_HOOK
00015 
00016 #if !defined (__ACE_INLINE__)
00017 #include "tao/Connection_Handler.inl"
00018 #endif /* __ACE_INLINE__ */
00019 
00020 ACE_RCSID (tao,
00021            Connection_Handler,
00022            "$Id: Connection_Handler.cpp 80603 2008-02-11 22:14:39Z johnc $")
00023 
00024 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00025 
00026 TAO_Connection_Handler::TAO_Connection_Handler (TAO_ORB_Core *orb_core)
00027   : orb_core_ (orb_core),
00028     transport_ (0),
00029     connection_pending_ (false)
00030 {
00031   // @todo: We need to have a distinct option/ method in the resource
00032   // factory for this and TAO_Transport.
00033   this->lock_ =
00034     this->orb_core_->resource_factory ()->create_cached_connection_lock ();
00035 
00036   // Put ourselves in the connection wait state as soon as we get
00037   // created
00038   this->state_changed (TAO_LF_Event::LFS_CONNECTION_WAIT,
00039                        this->orb_core_->leader_follower ());
00040 }
00041 
00042 TAO_Connection_Handler::~TAO_Connection_Handler (void)
00043 {
00044   // @@ TODO Use auto_ptr<>
00045   delete this->lock_;
00046 
00047   //@@ CONNECTION_HANDLER_DESTRUCTOR_ADD_HOOK
00048 }
00049 
00050 int
00051 TAO_Connection_Handler::shared_open (void)
00052 {
00053   // This reference counting is related to asynch connections.  It
00054   // should probably be managed by the ACE_Strategy_Connector, since
00055   // that's really the reference being managed here.  also, whether
00056   // open ultimately succeeds or fails, the connection attempted is
00057   // ending, so the reference must be removed in any case.
00058   this->cancel_pending_connection();
00059 
00060   return 0;
00061 }
00062 
00063 int
00064 TAO_Connection_Handler::set_socket_option (ACE_SOCK &sock,
00065                                            int snd_size,
00066                                            int rcv_size)
00067 {
00068 #if !defined (ACE_LACKS_SOCKET_BUFSIZ)
00069 
00070   if (snd_size != 0
00071       && sock.set_option (SOL_SOCKET,
00072                           SO_SNDBUF,
00073                           (void *) &snd_size,
00074                           sizeof (snd_size)) == -1
00075       && errno != ENOTSUP)
00076   {
00077     return -1;
00078   }
00079 
00080   if (rcv_size != 0
00081       && sock.set_option (SOL_SOCKET,
00082                           SO_RCVBUF,
00083                           (void *) &rcv_size,
00084                           sizeof (int)) == -1
00085       && errno != ENOTSUP)
00086   {
00087     return -1;
00088   }
00089 #else
00090    ACE_UNUSED_ARG (snd_size);
00091    ACE_UNUSED_ARG (rcv_size);
00092 #endif /* !ACE_LACKS_SOCKET_BUFSIZ */
00093 
00094   // Set the close-on-exec flag for that file descriptor. If the
00095   // operation fails we are out of luck (some platforms do not support
00096   // it and return -1).
00097   (void) sock.enable (ACE_CLOEXEC);
00098 
00099   return 0;
00100 }
00101 
00102 int
00103 TAO_Connection_Handler::svc_i (void)
00104 {
00105   int result = 0;
00106 
00107   if (TAO_debug_level > 0)
00108     ACE_DEBUG ((LM_DEBUG,
00109                 ACE_TEXT ("TAO (%P|%t) - Connection_Handler::svc_i begin\n")));
00110 
00111   // Here we simply synthesize the "typical" event loop one might find
00112   // in a reactive handler, except that this can simply block waiting
00113   // for input.
00114 
00115   ACE_Time_Value *max_wait_time = 0;
00116   ACE_Time_Value timeout;
00117   ACE_Time_Value current_timeout;
00118 
00119   if (this->orb_core_->thread_per_connection_timeout (timeout))
00120     {
00121       current_timeout = timeout;
00122       max_wait_time = &current_timeout;
00123     }
00124 
00125   TAO_Resume_Handle rh (this->orb_core_,
00126                         ACE_INVALID_HANDLE);
00127 
00128   // We exit of the loop if
00129   // - If the ORB core is shutdown by another thread
00130   // - Or if the transport is null. This could happen if an error
00131   // occured.
00132   // - Or if during processing a return value of -1 is received.
00133   while (!this->orb_core_->has_shutdown ()
00134          && result >= 0)
00135     {
00136       // Let the transport know that it is used
00137       (void) this->transport ()->update_transport ();
00138 
00139       result = this->transport ()->handle_input (rh, max_wait_time);
00140 
00141       if (result == -1 && errno == ETIME)
00142         {
00143           // Ignore timeouts, they are only used to wake up and
00144           // shutdown.
00145           result = 0;
00146 
00147           // Reset errno to make sure we don't trip over an old value
00148           // of errno in case it is not reset when the recv() call
00149           // fails if the socket has been closed.
00150           errno = 0;
00151         }
00152       else if (result == -1)
00153         {
00154           // Something went wrong with the socket. Just quit
00155           return result;
00156         }
00157 
00158       current_timeout = timeout;
00159 
00160       if (TAO_debug_level > 0)
00161         ACE_DEBUG ((LM_DEBUG,
00162                     "TAO (%P|%t) - Connection_Handler::svc_i - "
00163                     "loop <%d>\n", current_timeout.msec ()));
00164     }
00165 
00166   if (TAO_debug_level > 0)
00167     ACE_DEBUG  ((LM_DEBUG,
00168                  "TAO (%P|%t) - Connection_Handler::svc_i end\n"));
00169 
00170   return result;
00171 }
00172 
00173 void
00174 TAO_Connection_Handler::transport (TAO_Transport* transport)
00175 {
00176   this->transport_ = transport;
00177 
00178   // Enable reference counting on the event handler.
00179   this->transport_->event_handler_i ()->reference_counting_policy ().value (
00180       ACE_Event_Handler::Reference_Counting_Policy::ENABLED
00181     );
00182 }
00183 
00184 int
00185 TAO_Connection_Handler::handle_output_eh (
00186     ACE_HANDLE, ACE_Event_Handler * eh)
00187 {
00188   // Let the transport that it is going to be used
00189   (void) this->transport ()->update_transport ();
00190 
00191   // Instantiate the resume handle here.. This will automatically
00192   // resume the handle once data is written..
00193   TAO_Resume_Handle resume_handle (this->orb_core (),
00194                                    eh->get_handle ());
00195 
00196   int return_value = 0;
00197   this->pre_io_hook (return_value);
00198   if (return_value != 0)
00199     {
00200       resume_handle.set_flag (TAO_Resume_Handle::TAO_HANDLE_LEAVE_SUSPENDED);
00201       return return_value;
00202     }
00203 
00204   return_value = this->transport ()->handle_output (0);
00205 
00206   this->pos_io_hook (return_value);
00207 
00208   if (return_value != 0)
00209     {
00210       resume_handle.set_flag (TAO_Resume_Handle::TAO_HANDLE_LEAVE_SUSPENDED);
00211     }
00212 
00213   return return_value;
00214 }
00215 
00216 int
00217 TAO_Connection_Handler::handle_input_eh (
00218   ACE_HANDLE h, ACE_Event_Handler *eh)
00219 {
00220   // If we can't process upcalls just return
00221   if (!this->transport ()->wait_strategy ()->can_process_upcalls ())
00222     {
00223       if (TAO_debug_level > 6)
00224         ACE_DEBUG ((LM_DEBUG,
00225                     "TAO (%P|%t) - Connection_Handler[%d]::handle_input_eh, "
00226                     "not going to handle_input on transport "
00227                     "because upcalls temporarily suspended on this thread\n",
00228                     this->transport()->id()));
00229       return 0;
00230     }
00231 
00232   int const result = this->handle_input_internal (h, eh);
00233 
00234   if (result == -1)
00235     {
00236       this->close_connection ();
00237       return 0;
00238     }
00239 
00240   return result;
00241 }
00242 
00243 int
00244 TAO_Connection_Handler::handle_input_internal (
00245     ACE_HANDLE h, ACE_Event_Handler * eh)
00246 {
00247   // Let the transport know that it is used
00248   (void) this->transport ()->update_transport ();
00249 
00250   // Grab the transport id now and use the cached value for printing
00251   // since the  transport could dissappear by the time the thread
00252   // returns.
00253   size_t const t_id =
00254     this->transport ()->id ();
00255 
00256   if (TAO_debug_level > 6)
00257     {
00258       ACE_HANDLE handle = eh->get_handle();
00259       ACE_DEBUG ((LM_DEBUG,
00260                   "TAO (%P|%t) - Connection_Handler[%d]::handle_input, "
00261                   "handle = %d/%d\n",
00262                   t_id, handle, h));
00263     }
00264 
00265   TAO_Resume_Handle resume_handle (this->orb_core (), eh->get_handle ());
00266 
00267   int return_value = 0;
00268 
00269   this->pre_io_hook (return_value);
00270   if (return_value != 0)
00271     return return_value;
00272 
00273   return_value = this->transport ()->handle_input (resume_handle);
00274 
00275   this->pos_io_hook (return_value);
00276 
00277   // Bug 1647; might need to change resume_handle's flag or
00278   // change handle_input return value.
00279   resume_handle.handle_input_return_value_hook(return_value);
00280 
00281   if (TAO_debug_level > 6)
00282     {
00283       ACE_HANDLE handle = eh->get_handle ();
00284       ACE_DEBUG ((LM_DEBUG,
00285                   "TAO (%P|%t) - Connection_Handler[%d]::handle_input, "
00286                   "handle = %d/%d, retval = %d\n",
00287                   t_id, handle, h, return_value));
00288     }
00289 
00290   if (return_value == -1)
00291     resume_handle.set_flag (TAO_Resume_Handle::TAO_HANDLE_LEAVE_SUSPENDED);
00292   return return_value;
00293 }
00294 
00295 int
00296 TAO_Connection_Handler::close_connection_eh (ACE_Event_Handler *eh)
00297 {
00298   // Save the ID for debugging messages
00299   ACE_HANDLE handle = eh->get_handle ();
00300 
00301   size_t const id = this->transport ()->id ();
00302   if (TAO_debug_level)
00303     {
00304       ACE_DEBUG  ((LM_DEBUG,
00305                    "TAO (%P|%t) - Connection_Handler[%d]::"
00306                    "close_connection_eh, purging entry from cache\n",
00307                    handle));
00308     }
00309 
00310   this->transport ()->pre_close ();
00311 
00312   // @@ This seems silly, but if we have no reason to be in the
00313   // reactor, then we dont remove ourselves.
00314   if (this->transport ()->wait_strategy ()->is_registered ())
00315     {
00316       ACE_Reactor *eh_reactor = eh->reactor ();
00317 
00318       if (this->orb_core_->has_shutdown () == 0)
00319         {
00320           // If the ORB is nil, get the reactor from orb_core which gets it
00321           // from LF.
00322           if (eh_reactor == 0)
00323             eh_reactor = this->transport()->orb_core()->reactor ();
00324         }
00325 
00326       // The Reactor must not be null, otherwise something else is
00327       // horribly broken.
00328       ACE_ASSERT (eh_reactor != 0);
00329 
00330       if (TAO_debug_level)
00331         {
00332           ACE_DEBUG  ((LM_DEBUG,
00333                        "TAO (%P|%t) - Connection_Handler[%d]::"
00334                        "close_connection_eh, removing from the reactor\n",
00335                        handle));
00336         }
00337 
00338       // Use id instead of handle. Why? "handle" may be invalid for RW
00339       // cases  when drop_reply_on_shutdown is on, and when the
00340       // orb_core is shutting down. This means that the handler will
00341       // be left behind in the reactor which would create problems
00342       // later. Just forcefully remove them. If none exists reactor
00343       // will make things safer.
00344       ACE_HANDLE tmp_handle = handle;
00345       if (this->orb_core_->has_shutdown ())
00346         tmp_handle = (ACE_HANDLE) id;
00347 
00348       eh_reactor->remove_handler (tmp_handle,
00349                                   ACE_Event_Handler::ALL_EVENTS_MASK |
00350                                   ACE_Event_Handler::DONT_CALL);
00351 
00352       // Also cancel any timers, we may create those for time-limited
00353       // buffering
00354       if (TAO_debug_level)
00355         {
00356           ACE_DEBUG  ((LM_DEBUG,
00357                        "TAO (%P|%t) - Connection_Handler[%d]::"
00358                        "close_connection_eh, cancel all timers\n",
00359                        handle));
00360         }
00361 
00362       eh_reactor->cancel_timer (eh);
00363 
00364       // @@ This seems silly, the reactor is a much better authority to
00365       //    find out if a handle is registered...
00366       this->transport ()->wait_strategy ()->is_registered (false);
00367     }
00368 
00369   // This call should be made only after the cache and reactor are
00370   // cleaned up. This call can make upcalls to the application which
00371   // in turn can make remote calls (Bug 1551 and Bug 1482). The remote
00372   // calls from the application can try to use this handler from the
00373   // cache or from the reactor. So clean them up before this is
00374   // called.
00375   this->transport ()->send_connection_closed_notifications ();
00376   this->state_changed (TAO_LF_Event::LFS_CONNECTION_CLOSED,
00377                        this->orb_core_->leader_follower ());
00378 
00379   if (TAO_debug_level)
00380     {
00381       ACE_DEBUG  ((LM_DEBUG,
00382                    "TAO (%P|%t) - Connection_Handler[%d]::"
00383                    "close_connection_eh\n",
00384                    id));
00385     }
00386 
00387   return 1;
00388 }
00389 
00390 /*
00391  * Comment hook to comment the base class implementations
00392  * that do nothing. Specialized versions from derived
00393  * class will directly override these methods. Add
00394  * all methods that are virtual, have do nothing implementations
00395  * within this hook for later specialization.
00396  */
00397 //@@ CONNECTION_HANDLER_SPL_COMMENT_HOOK_START
00398 
00399 int
00400 TAO_Connection_Handler::set_dscp_codepoint (CORBA::Boolean)
00401 {
00402   return 0;
00403 }
00404 
00405 int
00406 TAO_Connection_Handler::set_dscp_codepoint (CORBA::Long)
00407 {
00408   return 0;
00409 }
00410 
00411 int
00412 TAO_Connection_Handler::release_os_resources (void)
00413 {
00414   return 0;
00415 }
00416 
00417 //@@ CONNECTION_HANDLER_SPL_COMMENT_HOOK_END
00418 
00419 void
00420 TAO_Connection_Handler::pre_io_hook (int &)
00421 {
00422 }
00423 
00424 void
00425 TAO_Connection_Handler::pos_io_hook (int &)
00426 {
00427 }
00428 
00429 int
00430 TAO_Connection_Handler::close_handler (void)
00431 {
00432   this->state_changed (TAO_LF_Event::LFS_CONNECTION_CLOSED,
00433                        this->orb_core_->leader_follower ());
00434   this->transport ()->purge_entry();
00435   this->transport ()->remove_reference ();
00436 
00437   // @@ I think that if the connection_pending state is true
00438   // when close_handler is calld, we should probably release
00439   // another reference so that the connector doesn't have to
00440   // worry about it.
00441 
00442   return 0;
00443 }
00444 
00445 //@@ CONNECTION_HANDLER_SPL_METHODS_ADD_HOOK
00446 
00447 TAO_END_VERSIONED_NAMESPACE_DECL

Generated on Tue Feb 2 17:37:51 2010 for TAO by  doxygen 1.4.7