Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

Connector.cpp

Go to the documentation of this file.
00001 // Connector.cpp
00002 // $Id: Connector.cpp,v 1.1.1.4.2.1 2003/04/16 16:41:14 taoadmin Exp $
00003 
00004 #ifndef ACE_CONNECTOR_C
00005 #define ACE_CONNECTOR_C
00006 
00007 #include "ace/Connector.h"
00008 
00009 #if !defined (ACE_LACKS_PRAGMA_ONCE)
00010 # pragma once
00011 #endif /* ACE_LACKS_PRAGMA_ONCE */
00012 
00013 ACE_RCSID(ace, Connector, "$Id: Connector.cpp,v 1.1.1.4.2.1 2003/04/16 16:41:14 taoadmin Exp $")
00014 
00015 ACE_ALLOC_HOOK_DEFINE(ACE_Connector)
00016 
00017 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> void
00018 ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::dump (void) const
00019 {
00020   ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::dump");
00021 
00022   ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
00023   ACE_DEBUG ((LM_DEBUG,  ACE_LIB_TEXT ("\nclosing_ = %d"), this->closing_));
00024   ACE_DEBUG ((LM_DEBUG,  ACE_LIB_TEXT ("\nflags_ = %d"), this->flags_));
00025   this->handler_map_.dump ();
00026   ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
00027 }
00028 
00029 // Bridge method for creating a SVC_HANDLER.  The strategy for
00030 // creating a SVC_HANDLER are configured into the Acceptor via it's
00031 // <creation_strategy_>.  The default is to create a new SVC_HANDLER.
00032 // However, subclasses can override this strategy to perform
00033 // SVC_HANDLER creation in any way that they like (such as creating
00034 // subclass instances of SVC_HANDLER, using a singleton, dynamically
00035 // linking the handler, etc.).
00036 
00037 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
00038 ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::make_svc_handler (SVC_HANDLER *&sh)
00039 {
00040   ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::make_svc_handler");
00041 
00042   if (sh == 0)
00043     ACE_NEW_RETURN (sh,
00044                     SVC_HANDLER,
00045                     -1);
00046 
00047   // Set the reactor of the newly created <SVC_HANDLER> to the same
00048   // reactor that this <Connector> is using.
00049   sh->reactor (this->reactor ());
00050   return 0;
00051 }
00052 
00053 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
00054 ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::activate_svc_handler (SVC_HANDLER *svc_handler)
00055 {
00056   ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::activate_svc_handler");
00057   // No errors initially
00058   int error = 0;
00059 
00060   // See if we should enable non-blocking I/O on the <svc_handler>'s
00061   // peer.
00062   if (ACE_BIT_ENABLED (this->flags_, ACE_NONBLOCK) != 0)
00063     {
00064       if (svc_handler->peer ().enable (ACE_NONBLOCK) == -1)
00065         error = 1;
00066     }
00067   // Otherwise, make sure it's disabled by default.
00068   else if (svc_handler->peer ().disable (ACE_NONBLOCK) == -1)
00069     error = 1;
00070 
00071   // We are connected now, so try to open things up.
00072   if (error || svc_handler->open ((void *) this) == -1)
00073     {
00074       // Make sure to close down the <svc_handler> to avoid descriptor
00075       // leaks.
00076       svc_handler->close (0);
00077       return -1;
00078     }
00079   else
00080     return 0;
00081 }
00082 
00083 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> ACE_PEER_CONNECTOR &
00084 ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connector (void) const
00085 {
00086   return ACE_const_cast (ACE_PEER_CONNECTOR &, this->connector_);
00087 }
00088 
00089 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
00090 ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect_svc_handler (
00091   SVC_HANDLER *&svc_handler,
00092   const ACE_PEER_CONNECTOR_ADDR &remote_addr,
00093   ACE_Time_Value *timeout,
00094   const ACE_PEER_CONNECTOR_ADDR &local_addr,
00095   int reuse_addr,
00096   int flags,
00097   int perms)
00098 {
00099   ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect_svc_handler");
00100 
00101   return this->connector_.connect (svc_handler->peer (),
00102                                    remote_addr,
00103                                    timeout,
00104                                    local_addr,
00105                                    reuse_addr,
00106                                    flags,
00107                                    perms);
00108 }
00109 
00110 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
00111 ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect_svc_handler (
00112   SVC_HANDLER *&svc_handler,
00113   SVC_HANDLER *&sh_copy,
00114   const ACE_PEER_CONNECTOR_ADDR &remote_addr,
00115   ACE_Time_Value *timeout,
00116   const ACE_PEER_CONNECTOR_ADDR &local_addr,
00117   int reuse_addr,
00118   int flags,
00119   int perms)
00120 {
00121   ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect_svc_handler");
00122 
00123   sh_copy = svc_handler;
00124   return this->connector_.connect (svc_handler->peer (),
00125                                    remote_addr,
00126                                    timeout,
00127                                    local_addr,
00128                                    reuse_addr,
00129                                    flags,
00130                                    perms);
00131 }
00132 
00133 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
00134 ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::open (ACE_Reactor *r, int flags)
00135 {
00136   ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::open");
00137   this->reactor (r);
00138   this->flags_ = flags;
00139   this->closing_ = 0;
00140   return 0;
00141 }
00142 
00143 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1>
00144 ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::ACE_Connector (ACE_Reactor *r, int flags)
00145 {
00146   ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::ACE_Connector");
00147   (void) this->open (r, flags);
00148 }
00149 
00150 template <class SVC_HANDLER>
00151 ACE_Svc_Tuple<SVC_HANDLER>::ACE_Svc_Tuple (
00152   SVC_HANDLER *sh,
00153   ACE_HANDLE handle,
00154   const void *arg,
00155   long id)
00156   : svc_handler_ (sh),
00157     handle_ (handle),
00158     arg_ (arg),
00159     cancellation_id_ (id),
00160     refcount_ (1)
00161 {
00162   ACE_TRACE ("ACE_Svc_Tuple<SVC_HANDLER>::ACE_Svc_Tuple");
00163 }
00164 
00165 template <class SVC_HANDLER>
00166 ACE_Svc_Tuple<SVC_HANDLER>::~ACE_Svc_Tuple (void)
00167 {
00168 }
00169 
00170 template <class SVC_HANDLER> SVC_HANDLER *
00171 ACE_Svc_Tuple<SVC_HANDLER>::svc_handler (void)
00172 {
00173   ACE_TRACE ("ACE_Svc_Tuple<SVC_HANDLER>::svc_handler");
00174   return this->svc_handler_;
00175 }
00176 
00177 template <class SVC_HANDLER> const void *
00178 ACE_Svc_Tuple<SVC_HANDLER>::arg (void)
00179 {
00180   ACE_TRACE ("ACE_Svc_Tuple<SVC_HANDLER>::arg");
00181   return this->arg_;
00182 }
00183 
00184 template <class SVC_HANDLER> void
00185 ACE_Svc_Tuple<SVC_HANDLER>::arg (const void *v)
00186 {
00187   ACE_TRACE ("ACE_Svc_Tuple<SVC_HANDLER>::arg");
00188   this->arg_ = v;
00189 }
00190 
00191 template <class SVC_HANDLER> ACE_HANDLE
00192 ACE_Svc_Tuple<SVC_HANDLER>::handle (void)
00193 {
00194   ACE_TRACE ("ACE_Svc_Tuple<SVC_HANDLER>::handle");
00195   return this->handle_;
00196 }
00197 
00198 template <class SVC_HANDLER> void
00199 ACE_Svc_Tuple<SVC_HANDLER>::handle (ACE_HANDLE h)
00200 {
00201   ACE_TRACE ("ACE_Svc_Tuple<SVC_HANDLER>::handle");
00202   this->handle_ = h;
00203 }
00204 
00205 template <class SVC_HANDLER> long
00206 ACE_Svc_Tuple<SVC_HANDLER>::cancellation_id (void)
00207 {
00208   ACE_TRACE ("ACE_Svc_Tuple<SVC_HANDLER>::cancellation_id");
00209   return this->cancellation_id_;
00210 }
00211 
00212 template <class SVC_HANDLER> void
00213 ACE_Svc_Tuple<SVC_HANDLER>::cancellation_id (long id)
00214 {
00215   ACE_TRACE ("ACE_Svc_Tuple<SVC_HANDLER>::cancellation_id");
00216   this->cancellation_id_ = id;
00217 }
00218 
00219 template <class SVC_HANDLER> long
00220 ACE_Svc_Tuple<SVC_HANDLER>::incr_refcount (void)
00221 {
00222   ACE_TRACE ("ACE_Svc_Tuple<SVC_HANDLER>::incr_refcount");
00223   return ++this->refcount_;
00224 }
00225 
00226 template <class SVC_HANDLER> long
00227 ACE_Svc_Tuple<SVC_HANDLER>::decr_refcount (void)
00228 {
00229   ACE_TRACE ("ACE_Svc_Tuple<SVC_HANDLER>::decr_refcount");
00230   if (--this->refcount_ > 0)
00231     return this->refcount_;
00232 
00233   ACE_ASSERT (this->refcount_ == 0);
00234 
00235   delete this;
00236 
00237   return 0;
00238 }
00239 
00240 template <class SVC_HANDLER> void
00241 ACE_Svc_Tuple<SVC_HANDLER>::dump (void) const
00242 {
00243   ACE_TRACE ("ACE_Svc_Tuple<SVC_HANDLER>::dump");
00244 
00245   ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
00246   ACE_DEBUG ((LM_DEBUG,  ACE_LIB_TEXT ("svc_handler_ = %x"), this->svc_handler_));
00247   ACE_DEBUG ((LM_DEBUG,  ACE_LIB_TEXT ("\narg_ = %x"), this->arg_));
00248   ACE_DEBUG ((LM_DEBUG,  ACE_LIB_TEXT ("\ncancellation_id_ = %d"), this->cancellation_id_));
00249   ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
00250 }
00251 
00252 // This method is called if a connection times out before completing.
00253 // In this case, we call our cleanup_AST() method to cleanup the
00254 // descriptor from the ACE_Connector's table.
00255 
00256 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
00257 ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::handle_timeout (
00258   const ACE_Time_Value &tv,
00259   const void *arg)
00260 {
00261   ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::handle_timeout");
00262   AST *ast = 0;
00263 
00264   if (this->cleanup_AST (((AST *) arg)->handle (),
00265                          ast) == -1)
00266     {
00267       // Matches the creation time refcount for AST, which is 1
00268       this->decr_ast_refcount ((AST *) arg);
00269       return -1;
00270     }
00271   else
00272     {
00273       ACE_ASSERT (((AST *) arg) == ast);
00274 
00275       // We may need this seemingly unnecessary assignment to work
00276       // around a bug with MSVC++?
00277       SVC_HANDLER *sh = ast->svc_handler ();
00278 
00279       // Forward to the SVC_HANDLER the <arg> that was passed in as a
00280       // magic cookie during ACE_Connector::connect().  This gives the
00281       // SVC_HANDLER an opportunity to take corrective action (e.g.,
00282       // wait a few milliseconds and try to reconnect again.
00283       int result = sh->handle_timeout (tv, ast->arg ());
00284 
00285       // Matches the creation time refcount for AST, which is 1.
00286       this->decr_ast_refcount (ast);
00287 
00288       if (result == -1)
00289         sh->handle_close (sh->get_handle (),
00290                           ACE_Event_Handler::TIMER_MASK);
00291       return 0;
00292     }
00293 }
00294 
00295 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
00296 ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::cleanup_AST (
00297   ACE_HANDLE handle,
00298   ACE_Svc_Tuple<SVC_HANDLER> *&ast)
00299 {
00300   ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::cleanup_AST");
00301 
00302   ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX,
00303                             ace_mon,
00304                             this->mutex_,
00305                             -1));
00306 
00307   // Locate the ACE_Svc_Handler corresponding to the socket
00308   // descriptor.
00309   if (this->handler_map_.unbind (handle, ast) == -1)
00310     {
00311       // Error, entry not found in map.
00312       errno = ENOENT;
00313       return -1;
00314     }
00315 
00316   // Matches incr_refcount () in create_AST () after registering
00317   // with the map.
00318   ast->decr_refcount ();
00319 
00320   // Try to remove from ACE_Timer_Queue but if it's not there we
00321   // ignore the error.
00322   if (this->reactor ()->cancel_timer (ast->cancellation_id ()))
00323     {
00324       // Matches incr_refcount () in create_AST () after registering
00325       // the timer
00326       ast->decr_refcount ();
00327     }
00328 
00329 
00330   ACE_Reactor_Mask m =
00331     ACE_Event_Handler::ALL_EVENTS_MASK | ACE_Event_Handler::DONT_CALL;
00332 
00333   // Remove ACE_HANDLE from ACE_Reactor.
00334   if (this->reactor ()->remove_handler (handle, m) == 0)
00335     {
00336       // Matches incr_refcount () in create_AST () after registering
00337       // with the Reactor.
00338       ast->decr_refcount ();
00339     }
00340   return 0;
00341 }
00342 
00343 // Called when a failure occurs during asynchronous connection
00344 // establishment.  Simply delegate all work to this->handle_output().
00345 
00346 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
00347 ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::handle_input (ACE_HANDLE h)
00348 {
00349   ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::handle_input");
00350   AST *ast = 0;
00351 
00352   if (this->cleanup_AST (h, ast) != -1)
00353     {
00354       ACE_ASSERT (ast != 0);
00355       ast->svc_handler ()->close (0);
00356 
00357       // Matches the creation time refcount for AST, which is 1
00358       this->decr_ast_refcount (ast);
00359     }
00360 
00361   return 0; // Already removed from the ACE_Reactor.
00362 }
00363 
00364 // Finalize a connection established in non-blocking mode.  When a
00365 // non-blocking connect *succeeds* the descriptor becomes enabled for
00366 // writing...  Likewise, it is generally the case that when a
00367 // non-blocking connect *fails* the descriptor becomes enabled for
00368 // reading.
00369 
00370 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
00371 ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::handle_output (ACE_HANDLE handle)
00372 {
00373   ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::handle_output");
00374   AST *ast = 0;
00375 
00376   if (this->cleanup_AST (handle, ast) == -1)
00377     {
00378       return 0;
00379     }
00380   ACE_ASSERT (ast != 0);   // This shouldn't happen!
00381 
00382   // Try to find out if the reactor uses event associations for the
00383   // handles it waits on. If so we need to reset it.
00384   int reset_new_handle = this->reactor ()->uses_event_associations ();
00385 
00386   if (reset_new_handle)
00387     this->connector_.reset_new_handle (handle);
00388 
00389   // Transfer ownership of the ACE_HANDLE to the SVC_HANDLER.
00390   ast->svc_handler ()->set_handle (handle);
00391 
00392   ACE_PEER_CONNECTOR_ADDR raddr;
00393 
00394   // Check to see if we're connected.
00395   if (ast->svc_handler ()->peer ().get_remote_addr (raddr) != -1)
00396     this->activate_svc_handler (ast->svc_handler ());
00397   else // Somethings gone wrong, so close down...
00398     {
00399 #if defined (ACE_WIN32)
00400       // ACE_DEBUG ((LM_DEBUG, "errno %d; Sleeping to retry get_remote_addr\n", errno));
00401       // Win32 (at least prior to Windows 2000) has a timing problem.
00402       // If you check to see if the connection has completed too fast,
00403       // it will fail - so wait 35 milliseconds to let it catch up.
00404       ACE_Time_Value tv (0, ACE_NON_BLOCKING_BUG_DELAY);
00405       ACE_OS::sleep (tv);
00406       if (ast->svc_handler ()->peer ().get_remote_addr (raddr) != -1)
00407         this->activate_svc_handler (ast->svc_handler ());
00408       else // do the svc handler close below...
00409 #endif /* ACE_WIN32 */
00410        ast->svc_handler ()->close (0);
00411     }
00412   // Matches the creation time refcount for AST, which is 1
00413   this->decr_ast_refcount (ast);
00414   return 0;
00415 }
00416 
00417 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
00418 ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::resume_handler (void)
00419 {
00420   return ACE_Event_Handler::ACE_EVENT_HANDLER_NOT_RESUMED;
00421 }
00422 
00423 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
00424 ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::handle_exception (ACE_HANDLE h)
00425 {
00426   ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::handle_exception");
00427 
00428   // On Win32, the except mask must also be set for asynchronous
00429   // connects.
00430 
00431   return this->handle_output (h);
00432 }
00433 
00434 // Initiate connection to peer.
00435 
00436 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
00437 ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect (
00438   SVC_HANDLER *&sh,
00439   const ACE_PEER_CONNECTOR_ADDR &remote_addr,
00440   const ACE_Synch_Options &synch_options,
00441   const ACE_PEER_CONNECTOR_ADDR &local_addr,
00442   int reuse_addr,
00443   int flags,
00444   int perms)
00445 {
00446   return this->connect_i (sh,
00447                           0,
00448                           remote_addr,
00449                           synch_options,
00450                           local_addr,
00451                           reuse_addr,
00452                           flags,
00453                           perms);
00454 }
00455 
00456 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
00457 ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect (
00458   SVC_HANDLER *&sh,
00459   SVC_HANDLER *&sh_copy,
00460   const ACE_PEER_CONNECTOR_ADDR &remote_addr,
00461   const ACE_Synch_Options &synch_options,
00462   const ACE_PEER_CONNECTOR_ADDR &local_addr,
00463   int reuse_addr,
00464   int flags,
00465   int perms)
00466 {
00467   return this->connect_i (sh,
00468                           &sh_copy,
00469                           remote_addr,
00470                           synch_options,
00471                           local_addr,
00472                           reuse_addr,
00473                           flags,
00474                           perms);
00475 }
00476 
00477 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
00478 ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect_i (
00479   SVC_HANDLER *&sh,
00480   SVC_HANDLER **sh_copy,
00481   const ACE_PEER_CONNECTOR_ADDR &remote_addr,
00482   const ACE_Synch_Options &synch_options,
00483   const ACE_PEER_CONNECTOR_ADDR &local_addr,
00484   int reuse_addr,
00485   int flags,
00486   int perms)
00487 {
00488   ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect_i");
00489 
00490   // If the user hasn't supplied us with a <SVC_HANDLER> we'll use the
00491   // factory method to create one.  Otherwise, things will remain as
00492   // they are...
00493   if (this->make_svc_handler (sh) == -1)
00494     return -1;
00495 
00496   ACE_Time_Value *timeout;
00497   int use_reactor = synch_options[ACE_Synch_Options::USE_REACTOR];
00498 
00499   if (use_reactor)
00500     timeout = (ACE_Time_Value *) &ACE_Time_Value::zero;
00501   else
00502     timeout = (ACE_Time_Value *) synch_options.time_value ();
00503 
00504   int result;
00505   if (sh_copy == 0)
00506     result = this->connect_svc_handler (sh,
00507                                         remote_addr,
00508                                         timeout,
00509                                         local_addr,
00510                                         reuse_addr,
00511                                         flags,
00512                                         perms);
00513   else
00514     result = this->connect_svc_handler (sh,
00515                                         *sh_copy,
00516                                         remote_addr,
00517                                         timeout,
00518                                         local_addr,
00519                                         reuse_addr,
00520                                         flags,
00521                                         perms);
00522 
00523   // Delegate to connection strategy.
00524   if (result == -1)
00525     {
00526       if (use_reactor && errno == EWOULDBLOCK)
00527         {
00528           // If the connection hasn't completed and we are using
00529           // non-blocking semantics then register ourselves with the
00530           // ACE_Reactor so that it will call us back when the
00531           // connection is complete or we timeout, whichever comes
00532           // first...
00533           int result;
00534 
00535           if (sh_copy == 0)
00536             result = this->create_AST (sh, synch_options);
00537           else
00538             result = this->create_AST (*sh_copy, synch_options);
00539 
00540           // If for some reason the <create_AST> call failed, then
00541           // <errno> will be set to the new error.  If the call
00542           // succeeds, however, we need to make sure that <errno>
00543           // remains set to <EWOULDBLOCK>.
00544           if (result == 0)
00545             errno = EWOULDBLOCK;
00546         }
00547       else
00548         {
00549           // Save/restore errno.
00550           ACE_Errno_Guard error (errno);
00551           // Make sure to close down the service handler to avoid
00552           // handle leaks.
00553           if (sh_copy == 0)
00554             {
00555               if (sh)
00556                 sh->close (0);
00557             }
00558           else if (*sh_copy)
00559             (*sh_copy)->close (0);
00560         }
00561       return -1;
00562     }
00563   else
00564     // Activate immediately if we are connected.
00565     return this->activate_svc_handler (sh);
00566 }
00567 
00568 // Initiate connection to peer.
00569 
00570 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
00571 ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect_n (
00572   size_t n,
00573   SVC_HANDLER *sh[],
00574   ACE_PEER_CONNECTOR_ADDR remote_addrs[],
00575   ACE_TCHAR *failed_svc_handlers,
00576   const ACE_Synch_Options &synch_options)
00577 {
00578   int result = 0;
00579 
00580   for (size_t i = 0; i < n; i++)
00581     {
00582       if (this->connect (sh[i], remote_addrs[i], synch_options) == -1
00583           && !(synch_options[ACE_Synch_Options::USE_REACTOR]
00584                && errno == EWOULDBLOCK))
00585         {
00586           result = -1;
00587           if (failed_svc_handlers != 0)
00588             // Mark this entry as having failed.
00589             failed_svc_handlers[i] = 1;
00590         }
00591       else if (failed_svc_handlers != 0)
00592         // Mark this entry as having succeeded.
00593         failed_svc_handlers[i] = 0;
00594     }
00595 
00596   return result;
00597 }
00598 
00599 // Cancel a <svc_handler> that was started asynchronously.
00600 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
00601 ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::cancel (SVC_HANDLER *sh)
00602 {
00603   ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::cancel");
00604   MAP_ITERATOR mi (this->handler_map_);
00605 
00606   for (MAP_ENTRY *me = 0;
00607        mi.next (me) != 0;
00608        mi.advance ())
00609     if (me->int_id_->svc_handler () == sh)
00610       {
00611         AST *ast = 0;
00612 
00613         if (this->cleanup_AST (me->ext_id_, ast) != -1)
00614           this->decr_ast_refcount (ast);
00615 
00616         return 0;
00617       }
00618 
00619   return -1;
00620 }
00621 
00622 // Register the pending SVC_HANDLER with the map so that it can be
00623 // activated later on when the connection complets.
00624 
00625 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
00626 ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::create_AST (
00627   SVC_HANDLER *sh,
00628   const ACE_Synch_Options &synch_options)
00629 {
00630   ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::create_AST");
00631 
00632   ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX,
00633                             ace_mon,
00634                             this->mutex_,
00635                             -1));
00636 
00637   ACE_HANDLE handle = sh->get_handle ();
00638   AST *ast;
00639 
00640   // AST is created with a refcount
00641   ACE_NEW_RETURN (ast,
00642                   AST (sh,
00643                        handle,
00644                        synch_options.arg (), -1),
00645                   -1);
00646 
00647   // Register this with the reactor for connection events.
00648   ACE_Reactor_Mask mask = ACE_Event_Handler::CONNECT_MASK;
00649 
00650   // Bind ACE_Svc_Tuple with the ACE_HANDLE we're trying to connect.
00651   if (this->handler_map_.bind (handle, ast) == -1)
00652     goto fail1;
00653 
00654   // Increment the refcount of the AST to indicate registration with
00655   // the map.
00656   ast->incr_refcount ();
00657 
00658   if (this->reactor ()->register_handler (handle,
00659                                           this,
00660                                           mask) == -1)
00661     goto fail2;
00662 
00663   // Increment the refcount of the AST. This increment is for access
00664   // from the Reactor. Though we register <this> with the Reactor,
00665   // every dispatch from the Reactor actually looks for <ast> and
00666   // hence the refcount increment.
00667   (void) ast->incr_refcount ();
00668 
00669   {
00670     // If we're starting connection under timer control then we need to
00671     // schedule a timeout with the ACE_Reactor.
00672     ACE_Time_Value *tv =
00673       ACE_const_cast (ACE_Time_Value *,
00674                       synch_options.time_value ());
00675     if (tv != 0)
00676       {
00677         int cancellation_id =
00678           this->reactor ()->schedule_timer
00679           (this,
00680            (const void *) ast,
00681            *tv);
00682         if (cancellation_id == -1)
00683           goto fail3;
00684 
00685         // Increment the refcount of the AST. This increment is for access
00686         // from the timer queue. The same argument used for Rector
00687         // registration holds true here too.
00688         (void) ast->incr_refcount ();
00689 
00690         ast->cancellation_id (cancellation_id);
00691         return 0;
00692       }
00693   }
00694   return 0; // Ok, everything worked just fine...
00695 
00696   // Undo previous actions using the ol' "goto label and fallthru"
00697   // trick...
00698 fail3:
00699   this->reactor ()->remove_handler
00700     (this, mask | ACE_Event_Handler::DONT_CALL);
00701   /* FALLTHRU */
00702 fail2:
00703   this->handler_map_.unbind (handle);
00704   /* FALLTHRU */
00705 fail1:
00706 
00707   // Close the svc_handler
00708   sh->close (0);
00709 
00710   ast->decr_refcount ();
00711   return -1;
00712 }
00713 
00714 // Terminate the Client ACE_Connector by iterating over any
00715 // unconnected ACE_Svc_Handler's and removing them from the
00716 // ACE_Reactor.  Note that we can't call handle_close() back at this
00717 // point since we own these things and we'll just get called
00718 // recursively!
00719 
00720 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
00721 ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::close (void)
00722 {
00723   ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::close");
00724   return this->handle_close ();
00725 }
00726 
00727 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
00728 ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::handle_close (ACE_HANDLE, ACE_Reactor_Mask)
00729 {
00730   ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::handle_close");
00731 
00732   if (this->reactor () != 0 && this->closing_ == 0)
00733     {
00734       // We're closing down now, so make sure not to call ourselves
00735       // recursively via other calls to handle_close() (e.g., from the
00736       // Timer_Queue).
00737       this->closing_ = 1;
00738 
00739       for (;;)
00740         {
00741           // Create an iterator.
00742           MAP_ITERATOR iterator = this->handler_map_.begin ();
00743 
00744           // If we reach the end of the map, break the loop.
00745           if (iterator == this->handler_map_.end ())
00746             break;
00747 
00748           // Get the first handle.
00749           ACE_HANDLE handle = (*iterator).ext_id_;
00750 
00751           // Clean it up.
00752           AST *ast = 0;
00753           int r = this->cleanup_AST (handle, ast);
00754 
00755           // Close the svc_handler.
00756           if (r != -1)
00757             {
00758               ACE_ASSERT (ast != 0);
00759               ast->svc_handler ()->close (0);
00760 
00761               // Zap the ast.
00762               this->decr_ast_refcount (ast);
00763             }
00764 
00765 
00766         }
00767     }
00768 
00769   return 0;
00770 }
00771 
00772 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
00773 ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::fini (void)
00774 {
00775   ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::fini");
00776 
00777   // Make sure to call close here since our destructor might not be
00778   // called if we're being dynamically linked via the svc.conf.
00779   this->handler_map_.close ();
00780 
00781   // Make sure we call our handle_close(), not a subclass's!
00782   return ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::handle_close ();
00783 }
00784 
00785 // Hook called by the explicit dynamic linking facility.
00786 
00787 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
00788 ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::init (int, ACE_TCHAR *[])
00789 {
00790   ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::init");
00791   return -1;
00792 }
00793 
00794 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
00795 ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::suspend (void)
00796 {
00797   ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::suspend");
00798   return -1;
00799 }
00800 
00801 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
00802 ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::resume (void)
00803 {
00804   ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::resume");
00805   return -1;
00806 }
00807 
00808 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
00809 ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::info (ACE_TCHAR **strp, size_t length) const
00810 {
00811   ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::info");
00812   ACE_TCHAR buf[BUFSIZ];
00813 
00814   ACE_OS::sprintf (buf,
00815                    ACE_LIB_TEXT ("%s\t %s"),
00816                    ACE_LIB_TEXT ("ACE_Connector"),
00817                    ACE_LIB_TEXT ("# connector factory\n"));
00818 
00819   if (*strp == 0 && (*strp = ACE_OS::strdup (buf)) == 0)
00820     return -1;
00821   else
00822     ACE_OS::strsncpy (*strp, buf, length);
00823   return ACE_static_cast (int, ACE_OS::strlen (buf));
00824 }
00825 
00826 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1>
00827 ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::~ACE_Connector (void)
00828 {
00829   ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::~ACE_Connector");
00830   // We will call our handle_close(), not a subclass's, due to the way
00831   // that C++ destructors work.
00832   this->handle_close ();
00833 }
00834 
00835 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> long
00836 ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::incr_ast_refcount (
00837     ACE_Svc_Tuple<SVC_HANDLER> *ast)
00838 {
00839   ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::incr_ast_refcount");
00840   ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX,
00841                             ace_mon,
00842                             this->mutex_,
00843                             -1));
00844 
00845   return ast->incr_refcount ();
00846 }
00847 
00848 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> long
00849 ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::decr_ast_refcount (
00850     ACE_Svc_Tuple<SVC_HANDLER> *ast)
00851 {
00852   ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::decr_ast_refcount");
00853   ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX,
00854                             ace_mon,
00855                             this->mutex_,
00856                             -1));
00857 
00858   return ast->decr_refcount ();
00859 }
00860 
00861 /***********************************************************/
00862 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
00863 ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::open (ACE_Reactor *r, int flags)
00864 {
00865   ACE_TRACE ("ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::open");
00866   return this->open (r, 0, 0, 0, flags);
00867 }
00868 
00869 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
00870 ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::open
00871   (ACE_Reactor *r,
00872    ACE_Creation_Strategy<SVC_HANDLER> *cre_s,
00873    ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2> *conn_s,
00874    ACE_Concurrency_Strategy<SVC_HANDLER> *con_s,
00875    int flags)
00876 {
00877   ACE_TRACE ("ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::open");
00878 
00879   this->reactor (r);
00880 
00881   // @@ Not implemented yet.
00882   // this->flags_ = flags;
00883   ACE_UNUSED_ARG (flags);
00884 
00885   // Initialize the creation strategy.
00886 
00887   // First we decide if we need to clean up.
00888   if (this->creation_strategy_ != 0 &&
00889       this->delete_creation_strategy_ != 0 &&
00890       cre_s != 0)
00891     {
00892       delete this->creation_strategy_;
00893       this->creation_strategy_ = 0;
00894       this->delete_creation_strategy_ = 0;
00895     }
00896 
00897   if (cre_s != 0)
00898     this->creation_strategy_ = cre_s;
00899   else if (this->creation_strategy_ == 0)
00900     {
00901       ACE_NEW_RETURN (this->creation_strategy_,
00902                       CREATION_STRATEGY,
00903                       -1);
00904       this->delete_creation_strategy_ = 1;
00905     }
00906 
00907 
00908   // Initialize the accept strategy.
00909 
00910   if (this->connect_strategy_ != 0 &&
00911       this->delete_connect_strategy_ != 0 &&
00912       conn_s != 0)
00913     {
00914       delete this->connect_strategy_;
00915       this->connect_strategy_ = 0;
00916       this->delete_connect_strategy_ = 0;
00917     }
00918 
00919     if (conn_s != 0)
00920       this->connect_strategy_ = conn_s;
00921     else if (this->connect_strategy_ == 0)
00922       {
00923         ACE_NEW_RETURN (this->connect_strategy_,
00924                         CONNECT_STRATEGY,
00925                         -1);
00926         this->delete_connect_strategy_ = 1;
00927       }
00928 
00929   // Initialize the concurrency strategy.
00930 
00931   if (this->concurrency_strategy_ != 0 &&
00932       this->delete_concurrency_strategy_ != 0 &&
00933       con_s != 0)
00934     {
00935       delete this->concurrency_strategy_;
00936       this->concurrency_strategy_ = 0;
00937       this->delete_concurrency_strategy_ = 0;
00938     }
00939 
00940   if (con_s != 0)
00941     this->concurrency_strategy_ = con_s;
00942   else if (this->concurrency_strategy_ == 0)
00943     {
00944       ACE_NEW_RETURN (this->concurrency_strategy_,
00945                       CONCURRENCY_STRATEGY,
00946                       -1);
00947       this->delete_concurrency_strategy_ = 1;
00948     }
00949 
00950   return 0;
00951 }
00952 
00953 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1>
00954 ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::ACE_Strategy_Connector
00955   (ACE_Reactor *reactor,
00956    ACE_Creation_Strategy<SVC_HANDLER> *cre_s,
00957    ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2> *conn_s,
00958    ACE_Concurrency_Strategy<SVC_HANDLER> *con_s,
00959    int flags)
00960     : creation_strategy_ (0),
00961       delete_creation_strategy_ (0),
00962       connect_strategy_ (0),
00963       delete_connect_strategy_ (0),
00964       concurrency_strategy_ (0),
00965       delete_concurrency_strategy_ (0)
00966 {
00967   ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::ACE_Strategy_Connector");
00968 
00969   if (this->open (reactor, cre_s, conn_s, con_s, flags) == -1)
00970     ACE_ERROR ((LM_ERROR,  ACE_LIB_TEXT ("%p\n"),  ACE_LIB_TEXT ("ACE_Strategy_Connector::ACE_Strategy_Connector")));
00971 }
00972 
00973 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1>
00974 ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::~ACE_Strategy_Connector (void)
00975 {
00976   ACE_TRACE ("ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::~ACE_Strategy_Connector");
00977 
00978   // Close down
00979   this->close ();
00980 }
00981 
00982 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
00983 ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::close (void)
00984 {
00985   if (this->delete_creation_strategy_)
00986     delete this->creation_strategy_;
00987   this->delete_creation_strategy_ = 0;
00988   this->creation_strategy_ = 0;
00989 
00990   if (this->delete_connect_strategy_)
00991     delete this->connect_strategy_;
00992   this->delete_connect_strategy_ = 0;
00993   this->connect_strategy_ = 0;
00994 
00995   if (this->delete_concurrency_strategy_)
00996     delete this->concurrency_strategy_;
00997   this->delete_concurrency_strategy_ = 0;
00998   this->concurrency_strategy_ = 0;
00999 
01000   return SUPER::close ();
01001 }
01002 
01003 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
01004 ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::make_svc_handler (SVC_HANDLER *&sh)
01005 {
01006   return this->creation_strategy_->make_svc_handler (sh);
01007 }
01008 
01009 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
01010 ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect_svc_handler
01011   (SVC_HANDLER *&sh,
01012    const ACE_PEER_CONNECTOR_ADDR &remote_addr,
01013    ACE_Time_Value *timeout,
01014    const ACE_PEER_CONNECTOR_ADDR &local_addr,
01015    int reuse_addr,
01016    int flags,
01017    int perms)
01018 {
01019   return this->connect_strategy_->connect_svc_handler (sh,
01020                                                        remote_addr,
01021                                                        timeout,
01022                                                        local_addr,
01023                                                        reuse_addr,
01024                                                        flags,
01025                                                        perms);
01026 }
01027 
01028 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
01029 ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect_svc_handler
01030   (SVC_HANDLER *&sh,
01031    SVC_HANDLER *&sh_copy,
01032    const ACE_PEER_CONNECTOR_ADDR &remote_addr,
01033    ACE_Time_Value *timeout,
01034    const ACE_PEER_CONNECTOR_ADDR &local_addr,
01035    int reuse_addr,
01036    int flags,
01037    int perms)
01038 {
01039   return this->connect_strategy_->connect_svc_handler (sh,
01040                                                        sh_copy,
01041                                                        remote_addr,
01042                                                        timeout,
01043                                                        local_addr,
01044                                                        reuse_addr,
01045                                                        flags,
01046                                                        perms);
01047 }
01048 
01049 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
01050 ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::activate_svc_handler (SVC_HANDLER *svc_handler)
01051 {
01052   return this->concurrency_strategy_->activate_svc_handler (svc_handler, this);
01053 }
01054 
01055 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> ACE_Creation_Strategy<SVC_HANDLER> *
01056 ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::creation_strategy (void) const
01057 {
01058   return this->creation_strategy_;
01059 }
01060 
01061 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2> *
01062 ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect_strategy (void) const
01063 {
01064   return this->connect_strategy_;
01065 }
01066 
01067 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> ACE_Concurrency_Strategy<SVC_HANDLER> *
01068 ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::concurrency_strategy (void) const
01069 {
01070   return this->concurrency_strategy_;
01071 }
01072 
01073 #endif /* ACE_CONNECTOR_C */

Generated on Mon Jun 16 11:19:25 2003 for ACE by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002