00001 // -*- C++ -*- 00002 00003 //============================================================================= 00004 /** 00005 * @file Connector.h 00006 * 00007 * $Id: Connector.h 80826 2008-03-04 14:51:23Z wotte $ 00008 * 00009 * @author Douglas C. Schmidt <schmidt@cs.wustl.edu> 00010 */ 00011 //============================================================================= 00012 00013 #ifndef ACE_CONNECTOR_H 00014 #define ACE_CONNECTOR_H 00015 00016 #include /**/ "ace/pre.h" 00017 00018 #include "ace/Service_Object.h" 00019 00020 #if !defined (ACE_LACKS_PRAGMA_ONCE) 00021 # pragma once 00022 #endif /* ACE_LACKS_PRAGMA_ONCE */ 00023 00024 #include "ace/Strategies_T.h" 00025 #include "ace/Synch_Options.h" 00026 #include "ace/Unbounded_Set.h" 00027 00028 ACE_BEGIN_VERSIONED_NAMESPACE_DECL 00029 00030 /** 00031 * @class ACE_Connector_Base 00032 * 00033 * @brief This base interface allows ACE_NonBlocking_Connect_Handler 00034 * to only care about the SVC_HANDLER template parameter of the 00035 * ACE_Connector. Otherwise, ACE_NonBlocking_Connect_Handler would 00036 * have to be configured with all the template parameters that 00037 * ACE_Connector is configured with. 00038 */ 00039 template <class SVC_HANDLER> 00040 class ACE_Connector_Base 00041 { 00042 public: 00043 00044 virtual ~ACE_Connector_Base (void) {} 00045 00046 /// Initialize the Svc_Handler. 00047 virtual void initialize_svc_handler (ACE_HANDLE handle, 00048 SVC_HANDLER *svc_handler) = 0; 00049 00050 /// Return the handle set representing the non-blocking connects in 00051 /// progress. 00052 virtual ACE_Unbounded_Set<ACE_HANDLE> &non_blocking_handles (void) = 0; 00053 }; 00054 00055 /** 00056 * @class ACE_NonBlocking_Connect_Handler 00057 * 00058 * @brief Performs non-blocking connects on behalf of the Connector. 00059 */ 00060 template <class SVC_HANDLER> 00061 class ACE_NonBlocking_Connect_Handler : public ACE_Event_Handler 00062 { 00063 public: 00064 00065 /// Constructor. 00066 ACE_NonBlocking_Connect_Handler (ACE_Connector_Base<SVC_HANDLER> &connector, 00067 SVC_HANDLER *, 00068 long timer_id); 00069 00070 /// Close up and return underlying SVC_HANDLER through @c sh. 00071 /** 00072 * If the return value is true the close was performed succesfully, 00073 * implying that this object was removed from the reactor and thereby 00074 * (by means of reference counting decremented to 0) deleted. 00075 * If the return value is false, the close was not successful. 00076 * The @c sh does not have any connection to the return 00077 * value. The argument will return a valid svc_handler object if a 00078 * valid one exists within the object. Returning a valid svc_handler 00079 * pointer also invalidates the svc_handler contained in this 00080 * object. 00081 */ 00082 bool close (SVC_HANDLER *&sh); 00083 00084 /// Get SVC_HANDLER. 00085 SVC_HANDLER *svc_handler (void); 00086 00087 /// Get handle. 00088 ACE_HANDLE handle (void); 00089 00090 /// Set handle. 00091 void handle (ACE_HANDLE); 00092 00093 /// Get timer id. 00094 long timer_id (void); 00095 00096 /// Set timer id. 00097 void timer_id (long timer_id); 00098 00099 /// Called by ACE_Reactor when asynchronous connections fail. 00100 virtual int handle_input (ACE_HANDLE); 00101 00102 /// Called by ACE_Reactor when asynchronous connections succeed. 00103 virtual int handle_output (ACE_HANDLE); 00104 00105 /// Called by ACE_Reactor when asynchronous connections suceeds (on 00106 /// some platforms only). 00107 virtual int handle_exception (ACE_HANDLE fd); 00108 00109 /// This method is called if a connection times out before 00110 /// completing. 00111 virtual int handle_timeout (const ACE_Time_Value &tv, const void *arg); 00112 00113 /// Should Reactor resume us if we have been suspended before the upcall? 00114 virtual int resume_handler (void); 00115 00116 /// Dump the state of an object. 00117 void dump (void) const; 00118 00119 /// Declare the dynamic allocation hooks. 00120 ACE_ALLOC_HOOK_DECLARE; 00121 00122 private: 00123 00124 /// Connector base. 00125 ACE_Connector_Base<SVC_HANDLER> &connector_; 00126 00127 /// Associated SVC_HANDLER. 00128 SVC_HANDLER *svc_handler_; 00129 00130 /// Associated timer id. 00131 long timer_id_; 00132 }; 00133 00134 /** 00135 * @class ACE_Connector 00136 * 00137 * @brief Generic factory for actively connecting clients and creating 00138 * service handlers (SVC_HANDLERs). 00139 * 00140 * Implements the strategy for actively establishing connections with 00141 * clients. An ACE_Connector is parameterized by concrete types that 00142 * conform to the interfaces of PEER_CONNECTOR and SVC_HANDLER. The 00143 * PEER_CONNECTOR is instantiated with a transport mechanism that 00144 * actively establishes connections. The SVC_HANDLER is instantiated 00145 * with a concrete type that performs the application-specific 00146 * service. Both blocking and non-blocking connects are supported. 00147 * Further, non-blocking connects support timeouts. 00148 */ 00149 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> 00150 class ACE_Connector : public ACE_Connector_Base<SVC_HANDLER>, public ACE_Service_Object 00151 { 00152 public: 00153 00154 // Useful STL-style traits. 00155 typedef typename SVC_HANDLER::addr_type addr_type; 00156 typedef ACE_PEER_CONNECTOR connector_type; 00157 typedef SVC_HANDLER handler_type; 00158 typedef typename SVC_HANDLER::stream_type stream_type; 00159 typedef typename ACE_PEER_CONNECTOR::PEER_ADDR peer_addr_type; 00160 typedef ACE_PEER_CONNECTOR_ADDR ACE_PEER_ADDR_TYPEDEF; 00161 00162 /** 00163 * Initialize a connector. @a flags indicates how SVC_HANDLER's 00164 * should be initialized prior to being activated. Right now, the 00165 * only flag that is processed is ACE_NONBLOCK, which enabled 00166 * non-blocking I/O on the SVC_HANDLER when it is opened. 00167 */ 00168 ACE_Connector (ACE_Reactor *r = ACE_Reactor::instance (), 00169 int flags = 0); 00170 00171 /** 00172 * Initialize a connector. @a flags indicates how SVC_HANDLER's 00173 * should be initialized prior to being activated. Right now, the 00174 * only flag that is processed is ACE_NONBLOCK, which enabled 00175 * non-blocking I/O on the SVC_HANDLER when it is opened. 00176 */ 00177 virtual int open (ACE_Reactor *r = ACE_Reactor::instance (), 00178 int flags = 0); 00179 00180 /// Shutdown a connector and release resources. 00181 virtual ~ACE_Connector (void); 00182 00183 // = Connection establishment methods. 00184 00185 /** 00186 * Initiate connection of @a svc_handler to peer at @a remote_addr 00187 * using @a synch_options. If the caller wants to designate the 00188 * selected @a local_addr they can (and can also insist that the 00189 * @a local_addr be reused by passing a value @a reuse_addr == 00190 * 1). @a flags and @a perms can be used to pass any flags that are 00191 * needed to perform specific operations such as opening a file 00192 * within connect with certain permissions. If the connection fails 00193 * the <close> hook on the <svc_handler> will be called 00194 * automatically to prevent resource leaks. 00195 */ 00196 virtual int connect (SVC_HANDLER *&svc_handler, 00197 const ACE_PEER_CONNECTOR_ADDR &remote_addr, 00198 const ACE_Synch_Options &synch_options = ACE_Synch_Options::defaults, 00199 const ACE_PEER_CONNECTOR_ADDR &local_addr 00200 = (peer_addr_type &) ACE_PEER_CONNECTOR_ADDR_ANY, 00201 int reuse_addr = 0, 00202 int flags = O_RDWR, 00203 int perms = 0); 00204 00205 /** 00206 * This is a variation on the previous <connect> method. On cached 00207 * connectors the @a svc_handler_hint variable can be used as a hint 00208 * for future lookups. Since this variable is modified in the 00209 * context of the internal cache its use is thread-safe. But the 00210 * actual svc_handler for the current connection is returned in the 00211 * second parameter @a svc_handler. If the connection fails the 00212 * <close> hook on the <svc_handler> will be called automatically to 00213 * prevent resource leaks. 00214 */ 00215 virtual int connect (SVC_HANDLER *&svc_handler_hint, 00216 SVC_HANDLER *&svc_handler, 00217 const ACE_PEER_CONNECTOR_ADDR &remote_addr, 00218 const ACE_Synch_Options &synch_options = ACE_Synch_Options::defaults, 00219 const ACE_PEER_CONNECTOR_ADDR &local_addr 00220 = (peer_addr_type &) ACE_PEER_CONNECTOR_ADDR_ANY, 00221 int reuse_addr = 0, 00222 int flags = O_RDWR, 00223 int perms = 0); 00224 00225 /** 00226 * Initiate connection of @a n @a svc_handlers to peers at 00227 * @a remote_addrs using @a synch_options. Returns -1 if failure 00228 * occurs and 0 otherwise. If @a failed_svc_handlers is non-NULL, a 00229 * 1 is placed in the corresponding index of @a failed_svc_handlers 00230 * for each <svc_handlers[i]> that failed to connect, else a 0 is 00231 * placed in that index. 00232 */ 00233 virtual int connect_n (size_t n, 00234 SVC_HANDLER *svc_handlers[], 00235 ACE_PEER_CONNECTOR_ADDR remote_addrs[], 00236 ACE_TCHAR *failed_svc_handlers = 0, 00237 const ACE_Synch_Options &synch_options = 00238 ACE_Synch_Options::defaults); 00239 00240 /** 00241 * Cancel the @a svc_handler that was started asynchronously. Note that 00242 * this is the only case when the Connector does not actively close 00243 * the @a svc_handler. It is left up to the caller of <cancel> to 00244 * decide the fate of the @a svc_handler. 00245 */ 00246 virtual int cancel (SVC_HANDLER *svc_handler); 00247 00248 /// Close down the Connector. All pending non-blocking connects are 00249 /// canceled and the corresponding svc_handler is closed. 00250 virtual int close (void); 00251 00252 /// Return the underlying PEER_CONNECTOR object. 00253 virtual ACE_PEER_CONNECTOR &connector (void) const; 00254 00255 /// Initialize Svc_Handler. 00256 virtual void initialize_svc_handler (ACE_HANDLE handle, 00257 SVC_HANDLER *svc_handler); 00258 00259 /// Set Reactor. 00260 virtual void reactor (ACE_Reactor *reactor); 00261 00262 /// Get Reactor. 00263 virtual ACE_Reactor *reactor (void) const; 00264 00265 /// Dump the state of an object. 00266 void dump (void) const; 00267 00268 /// Declare the dynamic allocation hooks. 00269 ACE_ALLOC_HOOK_DECLARE; 00270 00271 protected: 00272 // = Helpful typedefs. 00273 typedef ACE_NonBlocking_Connect_Handler<SVC_HANDLER> NBCH; 00274 00275 // = The following two methods define the Connector's strategies for 00276 // creating, connecting, and activating SVC_HANDLER's, respectively. 00277 00278 /** 00279 * Bridge method for creating a SVC_HANDLER. The default is to 00280 * create a new SVC_HANDLER only if @a sh == 0, else @a sh is 00281 * unchanged. However, subclasses can override this policy to 00282 * perform SVC_HANDLER creation in any way that they like (such as 00283 * creating subclass instances of SVC_HANDLER, using a singleton, 00284 * dynamically linking the handler, etc.). Returns -1 if failure, 00285 * else 0. 00286 */ 00287 virtual int make_svc_handler (SVC_HANDLER *&sh); 00288 00289 /** 00290 * Bridge method for connecting the @a svc_handler to the 00291 * @a remote_addr. The default behavior delegates to the 00292 * <PEER_CONNECTOR::connect>. 00293 */ 00294 virtual int connect_svc_handler (SVC_HANDLER *&svc_handler, 00295 const ACE_PEER_CONNECTOR_ADDR &remote_addr, 00296 ACE_Time_Value *timeout, 00297 const ACE_PEER_CONNECTOR_ADDR &local_addr, 00298 int reuse_addr, 00299 int flags, 00300 int perms); 00301 virtual int connect_svc_handler (SVC_HANDLER *&svc_handler, 00302 SVC_HANDLER *&sh_copy, 00303 const ACE_PEER_CONNECTOR_ADDR &remote_addr, 00304 ACE_Time_Value *timeout, 00305 const ACE_PEER_CONNECTOR_ADDR &local_addr, 00306 int reuse_addr, 00307 int flags, 00308 int perms); 00309 00310 /** 00311 * Bridge method for activating a @a svc_handler with the appropriate 00312 * concurrency strategy. The default behavior of this method is to 00313 * activate the SVC_HANDLER by calling its <open> method (which 00314 * allows the SVC_HANDLER to define its own concurrency strategy). 00315 * However, subclasses can override this strategy to do more 00316 * sophisticated concurrency activations (such as creating the 00317 * SVC_HANDLER as an "active object" via multi-threading or 00318 * multi-processing). 00319 */ 00320 virtual int activate_svc_handler (SVC_HANDLER *svc_handler); 00321 00322 /// Creates and registers ACE_NonBlocking_Connect_Handler. 00323 int nonblocking_connect (SVC_HANDLER *, 00324 const ACE_Synch_Options &); 00325 00326 /// Implementation of the connect methods. 00327 virtual int connect_i (SVC_HANDLER *&svc_handler, 00328 SVC_HANDLER **sh_copy, 00329 const ACE_PEER_CONNECTOR_ADDR &remote_addr, 00330 const ACE_Synch_Options &synch_options, 00331 const ACE_PEER_CONNECTOR_ADDR &local_addr, 00332 int reuse_addr, 00333 int flags, 00334 int perms); 00335 00336 /// Return the handle set representing the non-blocking connects in 00337 /// progress. 00338 ACE_Unbounded_Set<ACE_HANDLE> &non_blocking_handles (void); 00339 00340 // = Dynamic linking hooks. 00341 /// Default version does no work and returns -1. Must be overloaded 00342 /// by application developer to do anything meaningful. 00343 virtual int init (int argc, ACE_TCHAR *argv[]); 00344 00345 /// Calls handle_close() to shutdown the Connector gracefully. 00346 virtual int fini (void); 00347 00348 /// Default version returns address info in @a buf. 00349 virtual int info (ACE_TCHAR **strp, size_t length) const; 00350 00351 // = Service management hooks. 00352 /// Default version does no work and returns -1. Must be overloaded 00353 /// by application developer to do anything meaningful. 00354 virtual int suspend (void); 00355 00356 /// Default version does no work and returns -1. Must be overloaded 00357 /// by application developer to do anything meaningful. 00358 virtual int resume (void); 00359 00360 private: 00361 /// This is the peer connector factory. 00362 ACE_PEER_CONNECTOR connector_; 00363 00364 /** 00365 * Flags that indicate how SVC_HANDLER's should be initialized 00366 * prior to being activated. Right now, the only flag that is 00367 * processed is ACE_NONBLOCK, which enabled non-blocking I/O on 00368 * the SVC_HANDLER when it is opened. 00369 */ 00370 int flags_; 00371 00372 /// Pointer to the Reactor. 00373 ACE_Reactor *reactor_; 00374 00375 /// Handle set representing the non-blocking connects in progress. 00376 ACE_Unbounded_Set<ACE_HANDLE> non_blocking_handles_; 00377 00378 }; 00379 00380 /** 00381 * @class ACE_Strategy_Connector 00382 * 00383 * @brief Abstract factory for creating a service handler 00384 * (SVC_HANDLER), connecting the SVC_HANDLER, and activating the 00385 * SVC_HANDLER. 00386 * 00387 * Implements a flexible and extensible set of strategies for 00388 * actively establishing connections with clients. There are 00389 * three main strategies: (1) creating a SVC_HANDLER, (2) 00390 * actively initiating a new connection from the client, 00391 * and (3) activating the SVC_HANDLER with a 00392 * particular concurrency mechanism after the connection is established. 00393 */ 00394 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> 00395 class ACE_Strategy_Connector 00396 : public ACE_Connector <SVC_HANDLER, ACE_PEER_CONNECTOR_2> 00397 { 00398 public: 00399 00400 // Useful STL-style traits. 00401 typedef ACE_Creation_Strategy<SVC_HANDLER> 00402 creation_strategy_type; 00403 typedef ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2> 00404 connect_strategy_type; 00405 typedef ACE_Concurrency_Strategy<SVC_HANDLER> 00406 concurrency_strategy_type; 00407 typedef ACE_Connector <SVC_HANDLER, ACE_PEER_CONNECTOR_2> 00408 base_type; 00409 00410 // = Define some useful (old style) traits. 00411 typedef ACE_Creation_Strategy<SVC_HANDLER> 00412 CREATION_STRATEGY; 00413 typedef ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2> 00414 CONNECT_STRATEGY; 00415 typedef ACE_Concurrency_Strategy<SVC_HANDLER> 00416 CONCURRENCY_STRATEGY; 00417 typedef ACE_Connector <SVC_HANDLER, ACE_PEER_CONNECTOR_2> 00418 SUPER; 00419 00420 /** 00421 * Initialize a connector. @a flags indicates how <SVC_HANDLER>'s 00422 * should be initialized prior to being activated. Right now, the 00423 * only flag that is processed is ACE_NONBLOCK, which enabled 00424 * non-blocking I/O on the SVC_HANDLER when it is opened. 00425 */ 00426 ACE_Strategy_Connector (ACE_Reactor *r = ACE_Reactor::instance (), 00427 ACE_Creation_Strategy<SVC_HANDLER> * = 0, 00428 ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2> * = 0, 00429 ACE_Concurrency_Strategy<SVC_HANDLER> * = 0, 00430 int flags = 0); 00431 00432 /** 00433 * Initialize a connector. @a flags indicates how SVC_HANDLER's 00434 * should be initialized prior to being activated. Right now, the 00435 * only flag that is processed is ACE_NONBLOCK, which enabled 00436 * non-blocking I/O on the SVC_HANDLER when it is opened. 00437 * Default strategies would be created and used. 00438 */ 00439 virtual int open (ACE_Reactor *r, 00440 int flags); 00441 00442 /** 00443 * Initialize a connector. @a flags indicates how SVC_HANDLER's 00444 * should be initialized prior to being activated. Right now, the 00445 * only flag that is processed is ACE_NONBLOCK, which enabled 00446 * non-blocking I/O on the SVC_HANDLER when it is opened. 00447 */ 00448 virtual int open (ACE_Reactor *r = ACE_Reactor::instance (), 00449 ACE_Creation_Strategy<SVC_HANDLER> * = 0, 00450 ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2> * = 0, 00451 ACE_Concurrency_Strategy<SVC_HANDLER> * = 0, 00452 int flags = 0); 00453 00454 /// Shutdown a connector and release resources. 00455 virtual ~ACE_Strategy_Connector (void); 00456 00457 /// Close down the Connector 00458 virtual int close (void); 00459 00460 // = Strategies accessors 00461 virtual ACE_Creation_Strategy<SVC_HANDLER> *creation_strategy (void) const; 00462 virtual ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2> *connect_strategy (void) const; 00463 virtual ACE_Concurrency_Strategy<SVC_HANDLER> *concurrency_strategy (void) const; 00464 00465 protected: 00466 // = The following three methods define the <Connector>'s strategies 00467 // for creating, connecting, and activating SVC_HANDLER's, 00468 // respectively. 00469 00470 /** 00471 * Bridge method for creating a SVC_HANDLER. The strategy for 00472 * creating a SVC_HANDLER are configured into the Connector via 00473 * it's <creation_strategy_>. The default is to create a new 00474 * SVC_HANDLER only if @a sh == 0, else @a sh is unchanged. 00475 * However, subclasses can override this policy to perform 00476 * SVC_HANDLER creation in any way that they like (such as 00477 * creating subclass instances of SVC_HANDLER, using a singleton, 00478 * dynamically linking the handler, etc.). Returns -1 if failure, 00479 * else 0. 00480 */ 00481 virtual int make_svc_handler (SVC_HANDLER *&sh); 00482 00483 /** 00484 * Bridge method for connecting the new connection into the 00485 * SVC_HANDLER. The default behavior delegates to the 00486 * <PEER_CONNECTOR::connect> in the <Connect_Strategy>. 00487 */ 00488 virtual int connect_svc_handler (SVC_HANDLER *&sh, 00489 const ACE_PEER_CONNECTOR_ADDR &remote_addr, 00490 ACE_Time_Value *timeout, 00491 const ACE_PEER_CONNECTOR_ADDR &local_addr, 00492 int reuse_addr, 00493 int flags, 00494 int perms); 00495 00496 /** 00497 * Bridge method for connecting the new connection into the 00498 * SVC_HANDLER. The default behavior delegates to the 00499 * <PEER_CONNECTOR::connect> in the <Connect_Strategy>. 00500 * @a sh_copy is used to obtain a copy of the @a sh pointer, but that 00501 * can be kept in the stack; the motivation is a bit too long to 00502 * include here, but basically we want to modify @a sh safely, using 00503 * the internal locks in the Connect_Strategy, while saving a TSS 00504 * copy in @a sh_copy, usually located in the stack. 00505 */ 00506 virtual int connect_svc_handler (SVC_HANDLER *&sh, 00507 SVC_HANDLER *&sh_copy, 00508 const ACE_PEER_CONNECTOR_ADDR &remote_addr, 00509 ACE_Time_Value *timeout, 00510 const ACE_PEER_CONNECTOR_ADDR &local_addr, 00511 int reuse_addr, 00512 int flags, 00513 int perms); 00514 00515 /** 00516 * Bridge method for activating a SVC_HANDLER with the appropriate 00517 * concurrency strategy. The default behavior of this method is to 00518 * activate the SVC_HANDLER by calling its <open> method (which 00519 * allows the SVC_HANDLER to define its own concurrency strategy). 00520 * However, subclasses can override this strategy to do more 00521 * sophisticated concurrency activations (such as creating the 00522 * SVC_HANDLER as an "active object" via multi-threading or 00523 * multi-processing). 00524 */ 00525 virtual int activate_svc_handler (SVC_HANDLER *svc_handler); 00526 00527 // = Strategy objects. 00528 00529 /// Creation strategy for an Connector. 00530 CREATION_STRATEGY *creation_strategy_; 00531 00532 /// true if Connector created the creation strategy and thus should 00533 /// delete it, else false. 00534 bool delete_creation_strategy_; 00535 00536 /// Connect strategy for a Connector. 00537 CONNECT_STRATEGY *connect_strategy_; 00538 00539 /// true if Connector created the connect strategy and thus should 00540 /// delete it, else false. 00541 bool delete_connect_strategy_; 00542 00543 /// Concurrency strategy for an <Connector>. 00544 CONCURRENCY_STRATEGY *concurrency_strategy_; 00545 00546 /// true if Connector created the concurrency strategy and thus should 00547 /// delete it, else false. 00548 bool delete_concurrency_strategy_; 00549 }; 00550 00551 ACE_END_VERSIONED_NAMESPACE_DECL 00552 00553 #if defined (ACE_TEMPLATES_REQUIRE_SOURCE) 00554 #include "ace/Connector.cpp" 00555 #endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ 00556 00557 #if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) 00558 #pragma implementation ("Connector.cpp") 00559 #endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ 00560 00561 #include /**/ "ace/post.h" 00562 00563 #endif /* ACE_CONNECTOR_H */