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