Fixed typos
[ACE_TAO.git] / ACE / ace / Cached_Connect_Strategy_T.cpp
blob7987655b4d1ca5137a77a76f82181d6d437b197d
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)
7 #pragma once
8 #endif /* ACE_LACKS_PRAGMA_ONCE */
10 #include "ace/ACE.h"
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,
27 MUTEX *lock,
28 int delete_lock)
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,
34 ACE_TEXT ("%p\n"),
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 (void)
41 cleanup ();
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
47 (SVC_HANDLER *&sh,
48 const ACE_PEER_CONNECTOR_ADDR &remote_addr,
49 ACE_Time_Value *timeout,
50 const ACE_PEER_CONNECTOR_ADDR &local_addr,
51 bool reuse_addr,
52 int flags,
53 int perms,
54 ACE_Hash_Map_Entry<ACE_Refcounted_Hash_Recyclable<ACE_PEER_CONNECTOR_ADDR>, std::pair<SVC_HANDLER *, ATTRIBUTES> > *&entry,
55 int &found)
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);
64 found = 0;
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
83 found = 0;
85 // Reset hint
86 sh = 0;
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)
95 // Hint successful
96 found = 1;
98 // Tell the <svc_handler> that it should prepare itself for
99 // being recycled.
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.
108 int find_result = 0;
110 int result = this->caching_strategy ().notify_find (find_result,
111 possible_entry->int_id_.second);
113 if (result == -1)
114 return result;
116 else
118 // This hint will not be used.
119 possible_entry->ext_id_.decrement ();
121 // Hint not successful
122 found = 0;
124 // If <sh> is not connected to the correct address or is busy,
125 // we will not use it.
126 sh = 0;
129 if (found)
130 entry = possible_entry;
132 return 0;
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
137 (SVC_HANDLER *&sh,
138 const ACE_PEER_CONNECTOR_ADDR &remote_addr,
139 ACE_Time_Value *timeout,
140 const ACE_PEER_CONNECTOR_ADDR &local_addr,
141 bool reuse_addr,
142 int flags,
143 int perms,
144 ACE_Hash_Map_Entry<ACE_Refcounted_Hash_Recyclable<ACE_PEER_CONNECTOR_ADDR>, std::pair<SVC_HANDLER *, ATTRIBUTES> > *&entry,
145 int &found)
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,
161 true, // read ready
162 false, // write ready
163 true);// exception ready
165 if (state_result == 1)
168 if (sh->close () == -1)
169 return -1;
171 sh = 0;
173 // Cycle it once again..
175 else if ((state_result == -1) && (errno == ETIME))
177 // Found!!!
178 // Set the flag
179 found = 1;
181 // Tell the <svc_handler> that it should prepare itself for
182 // being recycled.
183 if (this->prepare_for_recycling (sh) == -1)
184 return -1;
186 return 0;
188 else
190 return -1;
194 // Not found...
196 // Set the flag
197 found = 0;
199 // We need to use a temporary variable here since we are not
200 // allowed to change <sh> because other threads may use this
201 // when we let go of the lock during the OS level connect.
203 // Note that making a new svc_handler, connecting remotely,
204 // binding to the map, and assigning of the hint and recycler
205 // should be atomic to the outside world.
206 SVC_HANDLER *potential_handler = 0;
208 // Create a new svc_handler
209 if (this->make_svc_handler (potential_handler) == -1)
210 return -1;
212 // Connect using the svc_handler.
213 if (this->cached_connect (potential_handler,
214 remote_addr,
215 timeout,
216 local_addr,
217 reuse_addr,
218 flags,
219 perms) == -1)
221 // Close the svc handler.
222 potential_handler->close (0);
224 return -1;
226 else
228 // Insert the new SVC_HANDLER instance into the cache.
229 if (this->connection_cache_.bind (search_addr,
230 potential_handler,
231 entry) == -1)
233 // Close the svc handler and reset <sh>.
234 potential_handler->close (0);
236 return -1;
239 // Everything succeeded as planned. Assign <sh> to
240 // <potential_handler>.
241 sh = potential_handler;
243 // Set the recycler and the recycling act
245 this->assign_recycler (sh, this, entry);
248 return 0;
251 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class CACHING_STRATEGY, class ATTRIBUTES, class MUTEX> int
252 ACE_Cached_Connect_Strategy_Ex<SVC_HANDLER, ACE_PEER_CONNECTOR_2, CACHING_STRATEGY, ATTRIBUTES, MUTEX>::cached_connect (SVC_HANDLER *&sh,
253 const ACE_PEER_CONNECTOR_ADDR &remote_addr,
254 ACE_Time_Value *timeout,
255 const ACE_PEER_CONNECTOR_ADDR &local_addr,
256 bool reuse_addr,
257 int flags,
258 int perms)
260 // Actively establish the connection. This is a timed blocking
261 // connect.
262 if (this->new_connection (sh,
263 remote_addr,
264 timeout,
265 local_addr,
266 reuse_addr,
267 flags,
268 perms) == -1)
270 // If connect() failed because of timeouts, we have to reject
271 // the connection entirely. This is necessary since currently
272 // there is no way for the non-blocking connects to complete and
273 // for the <Connector> to notify the cache of the completion of
274 // connect().
276 if (errno == EWOULDBLOCK || errno == ETIMEDOUT)
277 errno = ENOTSUP;
278 else if (ACE::out_of_handles (errno) || errno == EADDRINUSE)
280 // If the connect failed due to the process running out of
281 // file descriptors then, auto_purging of some connections
282 // are done from the CONNECTION_CACHE. This frees the
283 // descriptors which get used in the connect process and
284 // hence the same method is called again!
285 if (this->purge_connections () == -1)
286 return -1;
288 // Try connecting again.
289 if (this->new_connection (sh,
290 remote_addr,
291 timeout,
292 local_addr,
293 reuse_addr,
294 flags,
295 perms) == -1)
297 if (errno == EWOULDBLOCK || errno == ETIMEDOUT)
298 errno = ENOTSUP;
299 return -1;
302 else
304 return -1;
308 return 0;
313 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class CACHING_STRATEGY, class ATTRIBUTES, class MUTEX> int
314 ACE_Cached_Connect_Strategy_Ex<SVC_HANDLER, ACE_PEER_CONNECTOR_2, CACHING_STRATEGY, ATTRIBUTES, MUTEX>::connect_svc_handler_i
315 (SVC_HANDLER *&sh,
316 const ACE_PEER_CONNECTOR_ADDR &remote_addr,
317 ACE_Time_Value *timeout,
318 const ACE_PEER_CONNECTOR_ADDR &local_addr,
319 bool reuse_addr,
320 int flags,
321 int perms,
322 int& found)
324 CONNECTION_CACHE_ENTRY *entry = 0;
326 // Check if the user passed a hint svc_handler
327 if (sh != 0)
329 int result = this->check_hint_i (sh,
330 remote_addr,
331 timeout,
332 local_addr,
333 reuse_addr,
334 flags,
335 perms,
336 entry,
337 found);
338 if (result != 0)
339 return result;
342 // If not found
343 if (!found)
345 int result = this->find_or_create_svc_handler_i (sh,
346 remote_addr,
347 timeout,
348 local_addr,
349 reuse_addr,
350 flags,
351 perms,
352 entry,
353 found);
355 if (result != 0)
356 return result;
358 // Increment the refcount
359 entry->ext_id_.increment ();
362 if (entry)
364 // For all successful cases: mark the <svc_handler> in the cache
365 // as being <in_use>. Therefore recyclable is BUSY.
366 entry->ext_id_.recycle_state (ACE_RECYCLABLE_BUSY);
369 return 0;
373 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class CACHING_STRATEGY, class ATTRIBUTES, class MUTEX> int
374 ACE_Cached_Connect_Strategy_Ex<SVC_HANDLER, ACE_PEER_CONNECTOR_2, CACHING_STRATEGY, ATTRIBUTES, MUTEX>::cache_i (const void *recycling_act)
376 // The wonders and perils of ACT
377 CONNECTION_CACHE_ENTRY *entry = (CONNECTION_CACHE_ENTRY *) recycling_act;
379 // Mark the <svc_handler> in the cache as not being <in_use>.
380 // Therefore recyclable is IDLE.
381 entry->ext_id_.recycle_state (ACE_RECYCLABLE_IDLE_AND_PURGABLE);
383 return 0;
386 template<class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class CACHING_STRATEGY, class ATTRIBUTES, class MUTEX> int
387 ACE_Cached_Connect_Strategy_Ex<SVC_HANDLER, ACE_PEER_CONNECTOR_2, CACHING_STRATEGY, ATTRIBUTES, MUTEX>::recycle_state_i (const void *recycling_act,
388 ACE_Recyclable_State new_state)
390 // The wonders and perils of ACT
391 CONNECTION_CACHE_ENTRY *entry = (CONNECTION_CACHE_ENTRY *) recycling_act;
393 // Mark the <svc_handler> in the cache as not being <in_use>.
394 // Therefore recyclable is IDLE.
395 entry->ext_id_.recycle_state (new_state);
397 return 0;
400 template<class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class CACHING_STRATEGY, class ATTRIBUTES, class MUTEX> ACE_Recyclable_State
401 ACE_Cached_Connect_Strategy_Ex<SVC_HANDLER, ACE_PEER_CONNECTOR_2, CACHING_STRATEGY, ATTRIBUTES, MUTEX>::recycle_state_i (const void *recycling_act) const
403 // The wonders and perils of ACT
404 CONNECTION_CACHE_ENTRY *entry = (CONNECTION_CACHE_ENTRY *) recycling_act;
406 // Mark the <svc_handler> in the cache as not being <in_use>.
407 // Therefore recyclable is IDLE.
408 return entry->ext_id_.recycle_state ();
411 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class CACHING_STRATEGY, class ATTRIBUTES, class MUTEX> int
412 ACE_Cached_Connect_Strategy_Ex<SVC_HANDLER, ACE_PEER_CONNECTOR_2, CACHING_STRATEGY, ATTRIBUTES, MUTEX>::purge_i (const void *recycling_act)
414 // The wonders and perils of ACT
415 CONNECTION_CACHE_ENTRY *entry = (CONNECTION_CACHE_ENTRY *) recycling_act;
417 return this->connection_cache_.unbind (entry);
421 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class CACHING_STRATEGY, class ATTRIBUTES, class MUTEX> int
422 ACE_Cached_Connect_Strategy_Ex<SVC_HANDLER, ACE_PEER_CONNECTOR_2, CACHING_STRATEGY, ATTRIBUTES, MUTEX>::mark_as_closed_i (const void *recycling_act)
424 // The wonders and perils of ACT
425 CONNECTION_CACHE_ENTRY *entry = (CONNECTION_CACHE_ENTRY *) recycling_act;
427 // Mark the <svc_handler> in the cache as CLOSED.
428 entry->ext_id_.recycle_state (ACE_RECYCLABLE_CLOSED);
430 return 0;
433 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class CACHING_STRATEGY, class ATTRIBUTES, class MUTEX> int
434 ACE_Cached_Connect_Strategy_Ex<SVC_HANDLER, ACE_PEER_CONNECTOR_2, CACHING_STRATEGY, ATTRIBUTES, MUTEX>::cleanup_hint_i (const void *recycling_act,
435 void **act_holder)
437 // Reset the <*act_holder> in the confines and protection of the
438 // lock.
439 if (act_holder)
440 *act_holder = 0;
442 // The wonders and perils of ACT
443 CONNECTION_CACHE_ENTRY *entry = (CONNECTION_CACHE_ENTRY *) recycling_act;
445 // Decrement the refcount on the <svc_handler>.
446 int refcount = entry->ext_id_.decrement ();
448 // If the svc_handler state is closed and the refcount == 0, call
449 // close() on svc_handler.
450 if (entry->ext_id_.recycle_state () == ACE_RECYCLABLE_CLOSED &&
451 refcount == 0)
453 entry->int_id_.first->recycler (0, 0);
454 entry->int_id_.first->close ();
455 this->purge_i (entry);
458 return 0;
461 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class CACHING_STRATEGY, class ATTRIBUTES, class MUTEX> int
462 ACE_Cached_Connect_Strategy_Ex<SVC_HANDLER, ACE_PEER_CONNECTOR_2, CACHING_STRATEGY, ATTRIBUTES, MUTEX>::purge_connections (void)
464 return this->connection_cache_.purge ();
467 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class CACHING_STRATEGY, class ATTRIBUTES, class MUTEX> CACHING_STRATEGY &
468 ACE_Cached_Connect_Strategy_Ex<SVC_HANDLER, ACE_PEER_CONNECTOR_2, CACHING_STRATEGY, ATTRIBUTES, MUTEX>::caching_strategy (void)
470 return this->connection_cache_.caching_strategy ();
473 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class CACHING_STRATEGY, class ATTRIBUTES, class MUTEX> int
474 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,
475 ACE_Hash_Map_Entry<ACE_Refcounted_Hash_Recyclable<ACE_PEER_CONNECTOR_ADDR>, std::pair<SVC_HANDLER *, ATTRIBUTES> > *&entry)
477 typedef ACE_Hash_Map_Bucket_Iterator<REFCOUNTED_HASH_RECYCLABLE_ADDRESS,
478 std::pair<SVC_HANDLER *, ATTRIBUTES>,
479 ACE_Hash<REFCOUNTED_HASH_RECYCLABLE_ADDRESS>,
480 ACE_Equal_To<REFCOUNTED_HASH_RECYCLABLE_ADDRESS>,
481 ACE_Null_Mutex>
482 CONNECTION_CACHE_BUCKET_ITERATOR;
484 CONNECTION_CACHE_BUCKET_ITERATOR iterator (this->connection_cache_.map (),
485 search_addr);
487 CONNECTION_CACHE_BUCKET_ITERATOR end (this->connection_cache_.map (),
488 search_addr,
491 for (;
492 iterator != end;
493 ++iterator)
495 REFCOUNTED_HASH_RECYCLABLE_ADDRESS &addr = (*iterator).ext_id_;
497 if (addr.recycle_state () != ACE_RECYCLABLE_IDLE_AND_PURGABLE &&
498 addr.recycle_state () != ACE_RECYCLABLE_IDLE_BUT_NOT_PURGABLE)
499 continue;
501 if (addr.subject () != search_addr.subject ())
502 continue;
504 entry = &(*iterator);
507 // Update the caching attributes directly since we don't do a
508 // find() on the cache map.
511 // Indicates successful find.
512 int find_result = 0;
514 int result = this->caching_strategy ().notify_find (find_result,
515 entry->int_id_.second);
517 if (result == -1)
518 return result;
520 return 0;
523 return -1;
526 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class CACHING_STRATEGY, class ATTRIBUTES, class MUTEX> void
527 ACE_Cached_Connect_Strategy_Ex<SVC_HANDLER, ACE_PEER_CONNECTOR_2, CACHING_STRATEGY, ATTRIBUTES, MUTEX>::cleanup (void)
529 // Excluded other threads from changing the cache while we cleanup
530 ACE_GUARD (MUTEX, ace_mon, *this->lock_);
532 // Close down all cached service handlers.
533 typename CONNECTION_CACHE::ITERATOR iter = this->connection_cache_.begin ();
534 while (iter != this->connection_cache_.end ())
536 if ((*iter).second () != 0)
538 // save entry for future use
539 CONNECTION_CACHE_ENTRY *entry = (CONNECTION_CACHE_ENTRY *)
540 (*iter).second ()->recycling_act ();
542 // close handler
543 (*iter).second ()->recycler (0, 0);
544 (*iter).second ()->close ();
546 // remember next iter
547 typename CONNECTION_CACHE::ITERATOR next_iter = iter;
548 ++next_iter;
550 // purge the item from the hash
551 this->purge_i (entry);
553 // assign next iter
554 iter = next_iter;
556 else
557 ++iter;
561 /////////////////////////////////////////////////////////////////////////
563 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class CACHING_STRATEGY, class ATTRIBUTES, class MUTEX>
564 ACE_Bounded_Cached_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2, CACHING_STRATEGY, ATTRIBUTES, MUTEX>::ACE_Bounded_Cached_Connect_Strategy
565 (size_t max_size,
566 CACHING_STRATEGY &caching_s,
567 ACE_Creation_Strategy<SVC_HANDLER> *cre_s,
568 ACE_Concurrency_Strategy<SVC_HANDLER> *con_s,
569 ACE_Recycling_Strategy<SVC_HANDLER> *rec_s,
570 MUTEX *lock,
571 int delete_lock)
572 : CCSEBASE (caching_s, cre_s, con_s, rec_s, lock, delete_lock),
573 max_size_ (max_size)
577 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class CACHING_STRATEGY, class ATTRIBUTES, class MUTEX>
578 ACE_Bounded_Cached_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2, CACHING_STRATEGY, ATTRIBUTES, MUTEX>::~ACE_Bounded_Cached_Connect_Strategy(void)
582 template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class CACHING_STRATEGY, class ATTRIBUTES, class MUTEX>
584 ACE_Bounded_Cached_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2, CACHING_STRATEGY, ATTRIBUTES, MUTEX>::find_or_create_svc_handler_i
585 (SVC_HANDLER *&sh,
586 const ACE_PEER_CONNECTOR_ADDR &remote_addr,
587 ACE_Time_Value *timeout,
588 const ACE_PEER_CONNECTOR_ADDR &local_addr,
589 bool reuse_addr,
590 int flags,
591 int perms,
592 ACE_Hash_Map_Entry<ACE_Refcounted_Hash_Recyclable<ACE_PEER_CONNECTOR_ADDR>,
593 std::pair<SVC_HANDLER *, ATTRIBUTES> > *&entry,
594 int &found)
597 REFCOUNTED_HASH_RECYCLABLE_ADDRESS search_addr (remote_addr);
599 // Try to find the address in the cache. Only if we don't find it
600 // do we create a new <SVC_HANDLER> and connect it with the server.
601 while (this->find (search_addr, entry) != -1)
603 // We found a cached svc_handler.
604 // Get the cached <svc_handler>
605 sh = entry->int_id_.first ();
607 // Is the connection clean?
608 int state_result= ACE::handle_ready (sh->peer ().get_handle (),
609 &ACE_Time_Value::zero,
610 true, // read ready
611 false, // write ready
612 true);// exception ready
614 if (state_result == 1)
616 // The connection was disconnected during idle.
617 // close the svc_handler down.
618 if (sh->close () == -1)
620 ACE_ASSERT (0);
621 return -1;
623 sh = 0;
624 // and rotate once more...
626 else if ((state_result == -1) && (errno == ETIME))
628 // Found!!!
629 // Set the flag
630 found = 1;
632 // Tell the <svc_handler> that it should prepare itself for
633 // being recycled.
634 if (this->prepare_for_recycling (sh) == -1)
636 ACE_ASSERT (0);
637 return -1;
640 return 0;
642 else // some other return value or error...
644 ACE_ASSERT (0); // just to see it coming
646 ACELIB_ERROR ((LM_ERROR,
647 ACE_TEXT ("(%t)ACE_Bounded_Cached_Connect_Strategy<>::")
648 ACE_TEXT ("find_or_create_svc_handler_i - ")
649 ACE_TEXT ("error polling server socket state.\n")));
651 return -1;
655 // Not found...
657 // Set the flag
658 found = 0;
660 // Check the limit of handlers...
661 if ((this->max_size_ > 0) &&
662 (this->connection_cache_.current_size () >= this->max_size_))
664 // Try to purge idle connections
665 if (this->purge_connections () == -1)
666 return -1;
668 // Check limit again.
669 if (this->connection_cache_.current_size () >= this->max_size_)
670 // still too much!
671 return -1;
673 // OK, we have room now...
676 // We need to use a temporary variable here since we are not
677 // allowed to change <sh> because other threads may use this
678 // when we let go of the lock during the OS level connect.
680 // Note that making a new svc_handler, connecting remotely,
681 // binding to the map, and assigning of the hint and recycler
682 // should be atomic to the outside world.
683 SVC_HANDLER *potential_handler = 0;
685 // Create a new svc_handler
686 if (this->make_svc_handler (potential_handler) == -1)
687 return -1;
689 // Connect using the svc_handler.
690 if (this->cached_connect (potential_handler,
691 remote_addr,
692 timeout,
693 local_addr,
694 reuse_addr,
695 flags,
696 perms) == -1)
698 // Close the svc handler.
699 potential_handler->close (0);
700 return -1;
702 else
704 // Insert the new SVC_HANDLER instance into the cache.
705 if (this->connection_cache_.bind (search_addr,
706 potential_handler,
707 entry) == -1)
709 // Close the svc handler and reset <sh>.
710 potential_handler->close (0);
712 return -1;
715 // Everything succeeded as planned. Assign <sh> to
716 // <potential_handler>.
717 sh = potential_handler;
719 // Set the recycler and the recycling act
720 this->assign_recycler (sh, this, entry);
723 return 0;
726 ACE_END_VERSIONED_NAMESPACE_DECL
728 #endif /* ACE_CACHED_CONNECT_STRATEGY_T_CPP */