Connection_Handler.cpp

Go to the documentation of this file.
00001 //Connection_Handler.cpp,v 1.69 2006/06/20 05:46:28 jwillemsen Exp
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            "Connection_Handler.cpp,v 1.69 2006/06/20 05:46:28 jwillemsen Exp")
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 {
00030   // @@todo: We need to have a distinct option/ method in the resource
00031   // factory for this and TAO_Transport.
00032   this->lock_ =
00033     this->orb_core_->resource_factory ()->create_cached_connection_lock ();
00034 
00035   // Put ourselves in the connection wait state as soon as we get
00036   // created
00037   this->state_changed (TAO_LF_Event::LFS_CONNECTION_WAIT,
00038                        this->orb_core_->leader_follower ());
00039 }
00040 
00041 TAO_Connection_Handler::~TAO_Connection_Handler (void)
00042 {
00043   int const result =
00044     this->release_os_resources ();
00045 
00046   if (result == -1 && TAO_debug_level)
00047     {
00048       ACE_ERROR ((LM_ERROR,
00049                   "TAO (%P|%t) - Connection_Handler::~Connection_Handler,"
00050                   "release_os_resources() failed %m\n"));
00051     }
00052 
00053   // @@ TODO Use auto_ptr<>
00054   delete this->lock_;
00055 
00056   //@@ CONNECTION_HANDLER_DESTRUCTOR_ADD_HOOK
00057 }
00058 
00059 
00060 int
00061 TAO_Connection_Handler::set_socket_option (ACE_SOCK &sock,
00062                                            int snd_size,
00063                                            int rcv_size)
00064 {
00065 #if !defined (ACE_LACKS_SOCKET_BUFSIZ)
00066 
00067   if (snd_size != 0
00068       && sock.set_option (SOL_SOCKET,
00069                           SO_SNDBUF,
00070                           (void *) &snd_size,
00071                           sizeof (snd_size)) == -1
00072       && errno != ENOTSUP)
00073   {
00074     return -1;
00075   }
00076 
00077   if (rcv_size != 0
00078       && sock.set_option (SOL_SOCKET,
00079                           SO_RCVBUF,
00080                           (void *) &rcv_size,
00081                           sizeof (int)) == -1
00082       && errno != ENOTSUP)
00083   {
00084     return -1;
00085   }
00086 #else
00087    ACE_UNUSED_ARG (snd_size);
00088    ACE_UNUSED_ARG (rcv_size);
00089 #endif /* !ACE_LACKS_SOCKET_BUFSIZ */
00090 
00091   (void) sock.enable (ACE_CLOEXEC);
00092   // Set the close-on-exec flag for that file descriptor. If the
00093   // operation fails we are out of luck (some platforms do not support
00094   // it and return -1).
00095 
00096   return 0;
00097 }
00098 
00099 int
00100 TAO_Connection_Handler::svc_i (void)
00101 {
00102   int result = 0;
00103 
00104   if (TAO_debug_level > 0)
00105     ACE_DEBUG ((LM_DEBUG,
00106                 ACE_TEXT ("TAO (%P|%t) - Connection_Handler::svc_i begin\n")));
00107 
00108   // Here we simply synthesize the "typical" event loop one might find
00109   // in a reactive handler, except that this can simply block waiting
00110   // for input.
00111 
00112   ACE_Time_Value *max_wait_time = 0;
00113   ACE_Time_Value timeout;
00114   ACE_Time_Value current_timeout;
00115 
00116   if (this->orb_core_->thread_per_connection_timeout (timeout))
00117     {
00118       current_timeout = timeout;
00119       max_wait_time = &current_timeout;
00120     }
00121 
00122   TAO_Resume_Handle rh (this->orb_core_,
00123                         ACE_INVALID_HANDLE);
00124 
00125   // We exit of the loop if
00126   // - If the ORB core is shutdown by another thread
00127   // - Or if the transport is null. This could happen if an error
00128   // occured.
00129   // - Or if during processing a return value of -1 is received.
00130   while (!this->orb_core_->has_shutdown ()
00131          && result >= 0)
00132     {
00133       // Let the transport know that it is used
00134       (void) this->transport ()->update_transport ();
00135 
00136       result =
00137         this->transport ()->handle_input (rh,
00138                                           max_wait_time);
00139 
00140       if (result == -1 && errno == ETIME)
00141         {
00142           // Ignore timeouts, they are only used to wake up and
00143           // shutdown.
00144           result = 0;
00145 
00146           // Reset errno to make sure we don't trip over an old value
00147           // of errno in case it is not reset when the recv() call
00148           // fails if the socket has been closed.
00149           errno = 0;
00150         }
00151       else if (result == -1)
00152         {
00153           // Something went wrong with the socket. Just quit
00154           return result;
00155         }
00156 
00157       current_timeout = timeout;
00158 
00159       if (TAO_debug_level > 0)
00160         ACE_DEBUG ((LM_DEBUG,
00161                     "TAO (%P|%t) - Connection_Handler::svc_i - "
00162                     "loop <%d>\n", current_timeout.msec ()));
00163     }
00164 
00165   if (TAO_debug_level > 0)
00166     ACE_DEBUG  ((LM_DEBUG,
00167                  "TAO (%P|%t) - Connection_Handler::svc_i end\n"));
00168 
00169   return result;
00170 }
00171 
00172 void
00173 TAO_Connection_Handler::transport (TAO_Transport* transport)
00174 {
00175   this->transport_ = transport;
00176 
00177   // Enable reference counting on the event handler.
00178   this->transport_->event_handler_i ()->reference_counting_policy ().value (
00179       ACE_Event_Handler::Reference_Counting_Policy::ENABLED
00180     );
00181 }
00182 
00183 int
00184 TAO_Connection_Handler::handle_output_eh (
00185     ACE_HANDLE, ACE_Event_Handler * eh)
00186 {
00187   // Let the transport that it is going to be used
00188   (void) this->transport ()->update_transport ();
00189 
00190   // Instantiate the resume handle here.. This will automatically
00191   // resume the handle once data is written..
00192   TAO_Resume_Handle resume_handle (this->orb_core (),
00193                                    eh->get_handle ());
00194 
00195   int return_value = 0;
00196   this->pre_io_hook (return_value);
00197   if (return_value != 0)
00198     {
00199       resume_handle.set_flag (TAO_Resume_Handle::TAO_HANDLE_LEAVE_SUSPENDED);
00200       return return_value;
00201     }
00202 
00203   return_value = this->transport ()->handle_output ();
00204 
00205   this->pos_io_hook (return_value);
00206 
00207   if (return_value != 0)
00208     {
00209       resume_handle.set_flag (TAO_Resume_Handle::TAO_HANDLE_LEAVE_SUSPENDED);
00210     }
00211 
00212   return return_value;
00213 }
00214 
00215 int
00216 TAO_Connection_Handler::handle_input_eh (
00217   ACE_HANDLE h, ACE_Event_Handler *eh)
00218 {
00219   // If we can't process upcalls just return
00220   if (!this->transport ()->wait_strategy ()->can_process_upcalls ())
00221     {
00222       if (TAO_debug_level > 6)
00223         ACE_DEBUG ((LM_DEBUG,
00224                     "TAO (%P|%t) - Connection_Handler[%d]::handle_input_eh, "
00225                     "not going to handle_input on transport "
00226                     "because upcalls temporarily suspended on this thread\n",
00227                     this->transport()->id()));
00228       return 0;
00229     }
00230 
00231   int const result = this->handle_input_internal (h, eh);
00232 
00233   if (result == -1)
00234     {
00235       this->close_connection ();
00236       return 0;
00237     }
00238 
00239   return result;
00240 }
00241 
00242 int
00243 TAO_Connection_Handler::handle_input_internal (
00244     ACE_HANDLE h, ACE_Event_Handler * eh)
00245 {
00246   // Let the transport know that it is used
00247   (void) this->transport ()->update_transport ();
00248 
00249   // Grab the transport id now and use the cached value for printing
00250   // since the  transport could dissappear by the time the thread
00251   // returns.
00252   size_t const t_id =
00253     this->transport ()->id ();
00254 
00255   if (TAO_debug_level > 6)
00256     {
00257       ACE_HANDLE handle = eh->get_handle();
00258       ACE_DEBUG ((LM_DEBUG,
00259                   "TAO (%P|%t) - Connection_Handler[%d]::handle_input, "
00260                   "handle = %d/%d\n",
00261                   t_id, handle, h));
00262     }
00263 
00264   TAO_Resume_Handle resume_handle (this->orb_core (),
00265                                    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 ()->purge_entry ();
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 nill, 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::release_os_resources (void)
00407 {
00408   return 0;
00409 }
00410 
00411 //@@ CONNECTION_HANDLER_SPL_COMMENT_HOOK_END
00412 
00413 void
00414 TAO_Connection_Handler::pre_io_hook (int &)
00415 {
00416 }
00417 
00418 void
00419 TAO_Connection_Handler::pos_io_hook (int &)
00420 {
00421 }
00422 
00423 int
00424 TAO_Connection_Handler::close_handler (void)
00425 {
00426   this->state_changed (TAO_LF_Event::LFS_CONNECTION_CLOSED,
00427                        this->orb_core_->leader_follower ());
00428   this->transport ()->remove_reference ();
00429   return 0;
00430 }
00431 
00432 //@@ CONNECTION_HANDLER_SPL_METHODS_ADD_HOOK
00433 
00434 TAO_END_VERSIONED_NAMESPACE_DECL

Generated on Thu Nov 9 11:54:09 2006 for TAO by doxygen 1.3.6