1 #ifndef ACE_CACHED_CONNECT_STRATEGY_T_CPP
2 #define ACE_CACHED_CONNECT_STRATEGY_T_CPP
4 #include "ace/Cached_Connect_Strategy_T.h"
6 #if !defined (ACE_LACKS_PRAGMA_ONCE)
8 #endif /* ACE_LACKS_PRAGMA_ONCE */
11 #include "ace/Service_Repository.h"
12 #include "ace/Service_Types.h"
13 #include "ace/Thread_Manager.h"
14 #include "ace/WFMO_Reactor.h"
16 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
18 ACE_ALLOC_HOOK_DEFINE_Tcoccc (ACE_Cached_Connect_Strategy_Ex
)
19 ACE_ALLOC_HOOK_DEFINE_Tcoccc (ACE_Bounded_Cached_Connect_Strategy
)
21 template <class SVC_HANDLER
, ACE_PEER_CONNECTOR_1
, class CACHING_STRATEGY
, class ATTRIBUTES
, class MUTEX
>
22 ACE_Cached_Connect_Strategy_Ex
<SVC_HANDLER
, ACE_PEER_CONNECTOR_2
, CACHING_STRATEGY
, ATTRIBUTES
, MUTEX
>::ACE_Cached_Connect_Strategy_Ex
23 (CACHING_STRATEGY
&caching_s
,
24 ACE_Creation_Strategy
<SVC_HANDLER
> *cre_s
,
25 ACE_Concurrency_Strategy
<SVC_HANDLER
> *con_s
,
26 ACE_Recycling_Strategy
<SVC_HANDLER
> *rec_s
,
29 : CCSBASE (cre_s
, con_s
, rec_s
, lock
, delete_lock
),
30 connection_cache_ (caching_s
)
32 if (this->open (cre_s
, con_s
, rec_s
) == -1)
33 ACELIB_ERROR ((LM_ERROR
,
35 ACE_TEXT ("ACE_Cached_Connect_Strategy_Ex<SVC_HANDLER, ACE_PEER_CONNECTOR_2, CACHING_STRATEGY, ATTRIBUTES, MUTEX>\n")));
38 template <class SVC_HANDLER
, ACE_PEER_CONNECTOR_1
, class CACHING_STRATEGY
, class ATTRIBUTES
, class MUTEX
>
39 ACE_Cached_Connect_Strategy_Ex
<SVC_HANDLER
, ACE_PEER_CONNECTOR_2
, CACHING_STRATEGY
, ATTRIBUTES
, MUTEX
>::~ACE_Cached_Connect_Strategy_Ex ()
45 template <class SVC_HANDLER
, ACE_PEER_CONNECTOR_1
, class CACHING_STRATEGY
, class ATTRIBUTES
, class MUTEX
> int
46 ACE_Cached_Connect_Strategy_Ex
<SVC_HANDLER
, ACE_PEER_CONNECTOR_2
, CACHING_STRATEGY
, ATTRIBUTES
, MUTEX
>::check_hint_i
48 const ACE_PEER_CONNECTOR_ADDR
&remote_addr
,
49 ACE_Time_Value
*timeout
,
50 const ACE_PEER_CONNECTOR_ADDR
&local_addr
,
54 ACE_Hash_Map_Entry
<ACE_Refcounted_Hash_Recyclable
<ACE_PEER_CONNECTOR_ADDR
>, std::pair
<SVC_HANDLER
*, ATTRIBUTES
> > *&entry
,
57 ACE_UNUSED_ARG (remote_addr
);
58 ACE_UNUSED_ARG (timeout
);
59 ACE_UNUSED_ARG (local_addr
);
60 ACE_UNUSED_ARG (reuse_addr
);
61 ACE_UNUSED_ARG (flags
);
62 ACE_UNUSED_ARG (perms
);
66 // Get the recycling act for the svc_handler
67 CONNECTION_CACHE_ENTRY
*possible_entry
=
68 (CONNECTION_CACHE_ENTRY
*) sh
->recycling_act ();
70 // Check to see if the hint svc_handler has been closed down
71 if (possible_entry
->ext_id_
.recycle_state () == ACE_RECYCLABLE_CLOSED
)
73 // If close, decrement refcount
74 if (possible_entry
->ext_id_
.decrement () == 0)
76 // If refcount goes to zero, close down the svc_handler
77 possible_entry
->int_id_
.first
->recycler (0, 0);
78 possible_entry
->int_id_
.first
->close ();
79 this->purge_i (possible_entry
);
82 // Hint not successful
89 // If hint is not closed, see if it is connected to the correct
90 // address and is recyclable
91 else if ((possible_entry
->ext_id_
.recycle_state () == ACE_RECYCLABLE_IDLE_AND_PURGABLE
||
92 possible_entry
->ext_id_
.recycle_state () == ACE_RECYCLABLE_IDLE_BUT_NOT_PURGABLE
) &&
93 possible_entry
->ext_id_
.subject () == remote_addr
)
98 // Tell the <svc_handler> that it should prepare itself for
100 this->prepare_for_recycling (sh
);
103 // Update the caching attributes directly since we don't do a
104 // find() on the cache map.
107 // Indicates successful find.
110 int result
= this->caching_strategy ().notify_find (find_result
,
111 possible_entry
->int_id_
.second
);
118 // This hint will not be used.
119 possible_entry
->ext_id_
.decrement ();
121 // Hint not successful
124 // If <sh> is not connected to the correct address or is busy,
125 // we will not use it.
130 entry
= possible_entry
;
135 template <class SVC_HANDLER
, ACE_PEER_CONNECTOR_1
, class CACHING_STRATEGY
, class ATTRIBUTES
, class MUTEX
> int
136 ACE_Cached_Connect_Strategy_Ex
<SVC_HANDLER
, ACE_PEER_CONNECTOR_2
, CACHING_STRATEGY
, ATTRIBUTES
, MUTEX
>::find_or_create_svc_handler_i
138 const ACE_PEER_CONNECTOR_ADDR
&remote_addr
,
139 ACE_Time_Value
*timeout
,
140 const ACE_PEER_CONNECTOR_ADDR
&local_addr
,
144 ACE_Hash_Map_Entry
<ACE_Refcounted_Hash_Recyclable
<ACE_PEER_CONNECTOR_ADDR
>, std::pair
<SVC_HANDLER
*, ATTRIBUTES
> > *&entry
,
147 REFCOUNTED_HASH_RECYCLABLE_ADDRESS
search_addr (remote_addr
);
149 // Try to find the address in the cache. Only if we don't find it
150 // do we create a new <SVC_HANDLER> and connect it with the server.
151 while (this->find (search_addr
, entry
) != -1)
153 // We found a cached svc_handler.
154 // Get the cached <svc_handler>
155 sh
= entry
->int_id_
.first
;
157 // Is the connection clean?
158 int const state_result
=
159 ACE::handle_ready (sh
->peer ().get_handle (),
160 &ACE_Time_Value::zero
,
162 false, // write ready
163 true);// exception ready
165 if (state_result
== 1)
167 if (sh
->close () == -1)
172 // Cycle it once again..
174 else if ((state_result
== -1) && (errno
== ETIME
))
180 // Tell the <svc_handler> that it should prepare itself for
182 if (this->prepare_for_recycling (sh
) == -1)
198 // We need to use a temporary variable here since we are not
199 // allowed to change <sh> because other threads may use this
200 // when we let go of the lock during the OS level connect.
202 // Note that making a new svc_handler, connecting remotely,
203 // binding to the map, and assigning of the hint and recycler
204 // should be atomic to the outside world.
205 SVC_HANDLER
*potential_handler
= 0;
207 // Create a new svc_handler
208 if (this->make_svc_handler (potential_handler
) == -1)
211 // Connect using the svc_handler.
212 if (this->cached_connect (potential_handler
,
220 // Close the svc handler.
221 potential_handler
->close (0);
227 // Insert the new SVC_HANDLER instance into the cache.
228 if (this->connection_cache_
.bind (search_addr
,
232 // Close the svc handler and reset <sh>.
233 potential_handler
->close (0);
238 // Everything succeeded as planned. Assign <sh> to
239 // <potential_handler>.
240 sh
= potential_handler
;
242 // Set the recycler and the recycling act
244 this->assign_recycler (sh
, this, entry
);
250 template <class SVC_HANDLER
, ACE_PEER_CONNECTOR_1
, class CACHING_STRATEGY
, class ATTRIBUTES
, class MUTEX
> int
251 ACE_Cached_Connect_Strategy_Ex
<SVC_HANDLER
, ACE_PEER_CONNECTOR_2
, CACHING_STRATEGY
, ATTRIBUTES
, MUTEX
>::cached_connect (SVC_HANDLER
*&sh
,
252 const ACE_PEER_CONNECTOR_ADDR
&remote_addr
,
253 ACE_Time_Value
*timeout
,
254 const ACE_PEER_CONNECTOR_ADDR
&local_addr
,
259 // Actively establish the connection. This is a timed blocking
261 if (this->new_connection (sh
,
269 // If connect() failed because of timeouts, we have to reject
270 // the connection entirely. This is necessary since currently
271 // there is no way for the non-blocking connects to complete and
272 // for the <Connector> to notify the cache of the completion of
275 if (errno
== EWOULDBLOCK
|| errno
== ETIMEDOUT
)
277 else if (ACE::out_of_handles (errno
) || errno
== EADDRINUSE
)
279 // If the connect failed due to the process running out of
280 // file descriptors then, auto_purging of some connections
281 // are done from the CONNECTION_CACHE. This frees the
282 // descriptors which get used in the connect process and
283 // hence the same method is called again!
284 if (this->purge_connections () == -1)
287 // Try connecting again.
288 if (this->new_connection (sh
,
296 if (errno
== EWOULDBLOCK
|| errno
== ETIMEDOUT
)
311 template <class SVC_HANDLER
, ACE_PEER_CONNECTOR_1
, class CACHING_STRATEGY
, class ATTRIBUTES
, class MUTEX
> int
312 ACE_Cached_Connect_Strategy_Ex
<SVC_HANDLER
, ACE_PEER_CONNECTOR_2
, CACHING_STRATEGY
, ATTRIBUTES
, MUTEX
>::connect_svc_handler_i
314 const ACE_PEER_CONNECTOR_ADDR
&remote_addr
,
315 ACE_Time_Value
*timeout
,
316 const ACE_PEER_CONNECTOR_ADDR
&local_addr
,
322 CONNECTION_CACHE_ENTRY
*entry
= 0;
324 // Check if the user passed a hint svc_handler
327 int result
= this->check_hint_i (sh
,
343 int result
= this->find_or_create_svc_handler_i (sh
,
356 // Increment the refcount
357 entry
->ext_id_
.increment ();
362 // For all successful cases: mark the <svc_handler> in the cache
363 // as being <in_use>. Therefore recyclable is BUSY.
364 entry
->ext_id_
.recycle_state (ACE_RECYCLABLE_BUSY
);
371 template <class SVC_HANDLER
, ACE_PEER_CONNECTOR_1
, class CACHING_STRATEGY
, class ATTRIBUTES
, class MUTEX
> int
372 ACE_Cached_Connect_Strategy_Ex
<SVC_HANDLER
, ACE_PEER_CONNECTOR_2
, CACHING_STRATEGY
, ATTRIBUTES
, MUTEX
>::cache_i (const void *recycling_act
)
374 // The wonders and perils of ACT
375 CONNECTION_CACHE_ENTRY
*entry
= (CONNECTION_CACHE_ENTRY
*) recycling_act
;
377 // Mark the <svc_handler> in the cache as not being <in_use>.
378 // Therefore recyclable is IDLE.
379 entry
->ext_id_
.recycle_state (ACE_RECYCLABLE_IDLE_AND_PURGABLE
);
384 template<class SVC_HANDLER
, ACE_PEER_CONNECTOR_1
, class CACHING_STRATEGY
, class ATTRIBUTES
, class MUTEX
> int
385 ACE_Cached_Connect_Strategy_Ex
<SVC_HANDLER
, ACE_PEER_CONNECTOR_2
, CACHING_STRATEGY
, ATTRIBUTES
, MUTEX
>::recycle_state_i (const void *recycling_act
,
386 ACE_Recyclable_State new_state
)
388 // The wonders and perils of ACT
389 CONNECTION_CACHE_ENTRY
*entry
= (CONNECTION_CACHE_ENTRY
*) recycling_act
;
391 // Mark the <svc_handler> in the cache as not being <in_use>.
392 // Therefore recyclable is IDLE.
393 entry
->ext_id_
.recycle_state (new_state
);
398 template<class SVC_HANDLER
, ACE_PEER_CONNECTOR_1
, class CACHING_STRATEGY
, class ATTRIBUTES
, class MUTEX
> ACE_Recyclable_State
399 ACE_Cached_Connect_Strategy_Ex
<SVC_HANDLER
, ACE_PEER_CONNECTOR_2
, CACHING_STRATEGY
, ATTRIBUTES
, MUTEX
>::recycle_state_i (const void *recycling_act
) const
401 // The wonders and perils of ACT
402 CONNECTION_CACHE_ENTRY
*entry
= (CONNECTION_CACHE_ENTRY
*) recycling_act
;
404 // Mark the <svc_handler> in the cache as not being <in_use>.
405 // Therefore recyclable is IDLE.
406 return entry
->ext_id_
.recycle_state ();
409 template <class SVC_HANDLER
, ACE_PEER_CONNECTOR_1
, class CACHING_STRATEGY
, class ATTRIBUTES
, class MUTEX
> int
410 ACE_Cached_Connect_Strategy_Ex
<SVC_HANDLER
, ACE_PEER_CONNECTOR_2
, CACHING_STRATEGY
, ATTRIBUTES
, MUTEX
>::purge_i (const void *recycling_act
)
412 // The wonders and perils of ACT
413 CONNECTION_CACHE_ENTRY
*entry
= (CONNECTION_CACHE_ENTRY
*) recycling_act
;
415 return this->connection_cache_
.unbind (entry
);
419 template <class SVC_HANDLER
, ACE_PEER_CONNECTOR_1
, class CACHING_STRATEGY
, class ATTRIBUTES
, class MUTEX
> int
420 ACE_Cached_Connect_Strategy_Ex
<SVC_HANDLER
, ACE_PEER_CONNECTOR_2
, CACHING_STRATEGY
, ATTRIBUTES
, MUTEX
>::mark_as_closed_i (const void *recycling_act
)
422 // The wonders and perils of ACT
423 CONNECTION_CACHE_ENTRY
*entry
= (CONNECTION_CACHE_ENTRY
*) recycling_act
;
425 // Mark the <svc_handler> in the cache as CLOSED.
426 entry
->ext_id_
.recycle_state (ACE_RECYCLABLE_CLOSED
);
431 template <class SVC_HANDLER
, ACE_PEER_CONNECTOR_1
, class CACHING_STRATEGY
, class ATTRIBUTES
, class MUTEX
> int
432 ACE_Cached_Connect_Strategy_Ex
<SVC_HANDLER
, ACE_PEER_CONNECTOR_2
, CACHING_STRATEGY
, ATTRIBUTES
, MUTEX
>::cleanup_hint_i (const void *recycling_act
,
435 // Reset the <*act_holder> in the confines and protection of the
440 // The wonders and perils of ACT
441 CONNECTION_CACHE_ENTRY
*entry
= (CONNECTION_CACHE_ENTRY
*) recycling_act
;
443 // Decrement the refcount on the <svc_handler>.
444 int refcount
= entry
->ext_id_
.decrement ();
446 // If the svc_handler state is closed and the refcount == 0, call
447 // close() on svc_handler.
448 if (entry
->ext_id_
.recycle_state () == ACE_RECYCLABLE_CLOSED
&&
451 entry
->int_id_
.first
->recycler (0, 0);
452 entry
->int_id_
.first
->close ();
453 this->purge_i (entry
);
459 template <class SVC_HANDLER
, ACE_PEER_CONNECTOR_1
, class CACHING_STRATEGY
, class ATTRIBUTES
, class MUTEX
> int
460 ACE_Cached_Connect_Strategy_Ex
<SVC_HANDLER
, ACE_PEER_CONNECTOR_2
, CACHING_STRATEGY
, ATTRIBUTES
, MUTEX
>::purge_connections ()
462 return this->connection_cache_
.purge ();
465 template <class SVC_HANDLER
, ACE_PEER_CONNECTOR_1
, class CACHING_STRATEGY
, class ATTRIBUTES
, class MUTEX
> CACHING_STRATEGY
&
466 ACE_Cached_Connect_Strategy_Ex
<SVC_HANDLER
, ACE_PEER_CONNECTOR_2
, CACHING_STRATEGY
, ATTRIBUTES
, MUTEX
>::caching_strategy ()
468 return this->connection_cache_
.caching_strategy ();
471 template <class SVC_HANDLER
, ACE_PEER_CONNECTOR_1
, class CACHING_STRATEGY
, class ATTRIBUTES
, class MUTEX
> int
472 ACE_Cached_Connect_Strategy_Ex
<SVC_HANDLER
, ACE_PEER_CONNECTOR_2
, CACHING_STRATEGY
, ATTRIBUTES
, MUTEX
>::find (ACE_Refcounted_Hash_Recyclable
<ACE_PEER_CONNECTOR_ADDR
> &search_addr
,
473 ACE_Hash_Map_Entry
<ACE_Refcounted_Hash_Recyclable
<ACE_PEER_CONNECTOR_ADDR
>, std::pair
<SVC_HANDLER
*, ATTRIBUTES
> > *&entry
)
475 typedef ACE_Hash_Map_Bucket_Iterator
<REFCOUNTED_HASH_RECYCLABLE_ADDRESS
,
476 std::pair
<SVC_HANDLER
*, ATTRIBUTES
>,
477 ACE_Hash
<REFCOUNTED_HASH_RECYCLABLE_ADDRESS
>,
478 ACE_Equal_To
<REFCOUNTED_HASH_RECYCLABLE_ADDRESS
>,
480 CONNECTION_CACHE_BUCKET_ITERATOR
;
482 CONNECTION_CACHE_BUCKET_ITERATOR
iterator (this->connection_cache_
.map (),
485 CONNECTION_CACHE_BUCKET_ITERATOR
end (this->connection_cache_
.map (),
493 REFCOUNTED_HASH_RECYCLABLE_ADDRESS
&addr
= (*iterator
).ext_id_
;
495 if (addr
.recycle_state () != ACE_RECYCLABLE_IDLE_AND_PURGABLE
&&
496 addr
.recycle_state () != ACE_RECYCLABLE_IDLE_BUT_NOT_PURGABLE
)
499 if (addr
.subject () != search_addr
.subject ())
502 entry
= &(*iterator
);
505 // Update the caching attributes directly since we don't do a
506 // find() on the cache map.
509 // Indicates successful find.
512 int result
= this->caching_strategy ().notify_find (find_result
,
513 entry
->int_id_
.second
);
524 template <class SVC_HANDLER
, ACE_PEER_CONNECTOR_1
, class CACHING_STRATEGY
, class ATTRIBUTES
, class MUTEX
> void
525 ACE_Cached_Connect_Strategy_Ex
<SVC_HANDLER
, ACE_PEER_CONNECTOR_2
, CACHING_STRATEGY
, ATTRIBUTES
, MUTEX
>::cleanup ()
527 // Excluded other threads from changing the cache while we cleanup
528 ACE_GUARD (MUTEX
, ace_mon
, *this->lock_
);
530 // Close down all cached service handlers.
531 typename
CONNECTION_CACHE::ITERATOR iter
= this->connection_cache_
.begin ();
532 while (iter
!= this->connection_cache_
.end ())
534 if ((*iter
).second () != 0)
536 // save entry for future use
537 CONNECTION_CACHE_ENTRY
*entry
= (CONNECTION_CACHE_ENTRY
*)
538 (*iter
).second ()->recycling_act ();
541 (*iter
).second ()->recycler (0, 0);
542 (*iter
).second ()->close ();
544 // remember next iter
545 typename
CONNECTION_CACHE::ITERATOR next_iter
= iter
;
548 // purge the item from the hash
549 this->purge_i (entry
);
559 /////////////////////////////////////////////////////////////////////////
561 template <class SVC_HANDLER
, ACE_PEER_CONNECTOR_1
, class CACHING_STRATEGY
, class ATTRIBUTES
, class MUTEX
>
562 ACE_Bounded_Cached_Connect_Strategy
<SVC_HANDLER
, ACE_PEER_CONNECTOR_2
, CACHING_STRATEGY
, ATTRIBUTES
, MUTEX
>::ACE_Bounded_Cached_Connect_Strategy
564 CACHING_STRATEGY
&caching_s
,
565 ACE_Creation_Strategy
<SVC_HANDLER
> *cre_s
,
566 ACE_Concurrency_Strategy
<SVC_HANDLER
> *con_s
,
567 ACE_Recycling_Strategy
<SVC_HANDLER
> *rec_s
,
570 : CCSEBASE (caching_s
, cre_s
, con_s
, rec_s
, lock
, delete_lock
),
575 template <class SVC_HANDLER
, ACE_PEER_CONNECTOR_1
, class CACHING_STRATEGY
, class ATTRIBUTES
, class MUTEX
>
577 ACE_Bounded_Cached_Connect_Strategy
<SVC_HANDLER
, ACE_PEER_CONNECTOR_2
, CACHING_STRATEGY
, ATTRIBUTES
, MUTEX
>::find_or_create_svc_handler_i
579 const ACE_PEER_CONNECTOR_ADDR
&remote_addr
,
580 ACE_Time_Value
*timeout
,
581 const ACE_PEER_CONNECTOR_ADDR
&local_addr
,
585 ACE_Hash_Map_Entry
<ACE_Refcounted_Hash_Recyclable
<ACE_PEER_CONNECTOR_ADDR
>,
586 std::pair
<SVC_HANDLER
*, ATTRIBUTES
> > *&entry
,
589 REFCOUNTED_HASH_RECYCLABLE_ADDRESS
search_addr (remote_addr
);
591 // Try to find the address in the cache. Only if we don't find it
592 // do we create a new <SVC_HANDLER> and connect it with the server.
593 while (this->find (search_addr
, entry
) != -1)
595 // We found a cached svc_handler.
596 // Get the cached <svc_handler>
597 sh
= entry
->int_id_
.first ();
599 // Is the connection clean?
600 int state_result
= ACE::handle_ready (sh
->peer ().get_handle (),
601 &ACE_Time_Value::zero
,
603 false, // write ready
604 true);// exception ready
606 if (state_result
== 1)
608 // The connection was disconnected during idle.
609 // close the svc_handler down.
610 if (sh
->close () == -1)
616 // and rotate once more...
618 else if ((state_result
== -1) && (errno
== ETIME
))
624 // Tell the <svc_handler> that it should prepare itself for
626 if (this->prepare_for_recycling (sh
) == -1)
634 else // some other return value or error...
636 ACE_ASSERT (0); // just to see it coming
638 ACELIB_ERROR ((LM_ERROR
,
639 ACE_TEXT ("(%t)ACE_Bounded_Cached_Connect_Strategy<>::")
640 ACE_TEXT ("find_or_create_svc_handler_i - ")
641 ACE_TEXT ("error polling server socket state.\n")));
652 // Check the limit of handlers...
653 if ((this->max_size_
> 0) &&
654 (this->connection_cache_
.current_size () >= this->max_size_
))
656 // Try to purge idle connections
657 if (this->purge_connections () == -1)
660 // Check limit again.
661 if (this->connection_cache_
.current_size () >= this->max_size_
)
665 // OK, we have room now...
668 // We need to use a temporary variable here since we are not
669 // allowed to change <sh> because other threads may use this
670 // when we let go of the lock during the OS level connect.
672 // Note that making a new svc_handler, connecting remotely,
673 // binding to the map, and assigning of the hint and recycler
674 // should be atomic to the outside world.
675 SVC_HANDLER
*potential_handler
= 0;
677 // Create a new svc_handler
678 if (this->make_svc_handler (potential_handler
) == -1)
681 // Connect using the svc_handler.
682 if (this->cached_connect (potential_handler
,
690 // Close the svc handler.
691 potential_handler
->close (0);
696 // Insert the new SVC_HANDLER instance into the cache.
697 if (this->connection_cache_
.bind (search_addr
,
701 // Close the svc handler and reset <sh>.
702 potential_handler
->close (0);
707 // Everything succeeded as planned. Assign <sh> to
708 // <potential_handler>.
709 sh
= potential_handler
;
711 // Set the recycler and the recycling act
712 this->assign_recycler (sh
, this, entry
);
718 ACE_END_VERSIONED_NAMESPACE_DECL
720 #endif /* ACE_CACHED_CONNECT_STRATEGY_T_CPP */