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