00001 #include "ace_pch.h"
00002
00003
00004 #ifndef CACHED_CONNECT_STRATEGY_T_C
00005 #define CACHED_CONNECT_STRATEGY_T_C
00006
00007 #include "ace/Cached_Connect_Strategy_T.h"
00008
00009 #if !defined (ACE_LACKS_PRAGMA_ONCE)
00010 #define ACE_LACKS_PRAGMA_ONCE
00011 #endif
00012
00013 #include "ace/ACE.h"
00014 #include "ace/Service_Repository.h"
00015 #include "ace/Synch.h"
00016 #include "ace/Service_Types.h"
00017 #include "ace/Thread_Manager.h"
00018 #include "ace/WFMO_Reactor.h"
00019 #include "ace/Pair_T.h"
00020
00021 ACE_RCSID(ace, Cached_Connect_Strategy_T, "$Id: Cached_Connect_Strategy_T.cpp,v 1.1.1.3.64.1 2003/03/13 19:44:20 chad Exp $")
00022
00023 #define ACE_T1 class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class CACHING_STRATEGY, class ATTRIBUTES, class MUTEX
00024 #define ACE_T2 SVC_HANDLER, ACE_PEER_CONNECTOR_2, CACHING_STRATEGY, ATTRIBUTES, MUTEX
00025
00026 template <ACE_T1>
00027 ACE_Cached_Connect_Strategy_Ex<ACE_T2>::ACE_Cached_Connect_Strategy_Ex
00028 (CACHING_STRATEGY &caching_s,
00029 ACE_Creation_Strategy<SVC_HANDLER> *cre_s,
00030 ACE_Concurrency_Strategy<SVC_HANDLER> *con_s,
00031 ACE_Recycling_Strategy<SVC_HANDLER> *rec_s,
00032 MUTEX *lock,
00033 int delete_lock)
00034 : CCSBASE (cre_s, con_s, rec_s, lock, delete_lock),
00035 connection_cache_ (caching_s)
00036 {
00037 if (this->open (cre_s, con_s, rec_s) == -1)
00038 ACE_ERROR ((LM_ERROR,
00039 ACE_LIB_TEXT ("%p\n"),
00040 ACE_LIB_TEXT ("ACE_Cached_Connect_Strategy_Ex<ACE_T2>\n")));
00041 }
00042
00043 template <ACE_T1>
00044 ACE_Cached_Connect_Strategy_Ex<ACE_T2>::~ACE_Cached_Connect_Strategy_Ex (void)
00045 {
00046 cleanup ();
00047 }
00048
00049
00050 template <ACE_T1> int
00051 ACE_Cached_Connect_Strategy_Ex<ACE_T2>::check_hint_i
00052 (SVC_HANDLER *&sh,
00053 const ACE_PEER_CONNECTOR_ADDR &remote_addr,
00054 ACE_Time_Value *timeout,
00055 const ACE_PEER_CONNECTOR_ADDR &local_addr,
00056 int reuse_addr,
00057 int flags,
00058 int perms,
00059 ACE_Hash_Map_Entry<ACE_Refcounted_Hash_Recyclable<ACE_PEER_CONNECTOR_ADDR>, ACE_Pair<SVC_HANDLER *, ATTRIBUTES> > *&entry,
00060 int &found)
00061 {
00062 ACE_UNUSED_ARG (remote_addr);
00063 ACE_UNUSED_ARG (timeout);
00064 ACE_UNUSED_ARG (local_addr);
00065 ACE_UNUSED_ARG (reuse_addr);
00066 ACE_UNUSED_ARG (flags);
00067 ACE_UNUSED_ARG (perms);
00068
00069 found = 0;
00070
00071
00072 CONNECTION_CACHE_ENTRY *possible_entry = (CONNECTION_CACHE_ENTRY *) sh->recycling_act ();
00073
00074
00075 if (possible_entry->ext_id_.recycle_state () == ACE_RECYCLABLE_CLOSED)
00076 {
00077
00078 if (possible_entry->ext_id_.decrement () == 0)
00079 {
00080
00081 possible_entry->int_id_.first ()->recycler (0, 0);
00082 possible_entry->int_id_.first ()->close ();
00083 this->purge_i (possible_entry);
00084 }
00085
00086
00087 found = 0;
00088
00089
00090 sh = 0;
00091 }
00092
00093
00094
00095 else if ((possible_entry->ext_id_.recycle_state () == ACE_RECYCLABLE_IDLE_AND_PURGABLE ||
00096 possible_entry->ext_id_.recycle_state () == ACE_RECYCLABLE_IDLE_BUT_NOT_PURGABLE) &&
00097 possible_entry->ext_id_.subject () == remote_addr)
00098 {
00099
00100 found = 1;
00101
00102
00103
00104 this->prepare_for_recycling (sh);
00105
00106
00107
00108
00109
00110
00111
00112 int find_result = 0;
00113
00114 int result = this->caching_strategy ().notify_find (find_result,
00115 possible_entry->int_id_.second ());
00116
00117 if (result == -1)
00118 return result;
00119 }
00120 else
00121 {
00122
00123 possible_entry->ext_id_.decrement ();
00124
00125
00126 found = 0;
00127
00128
00129
00130 sh = 0;
00131 }
00132
00133 if (found)
00134 entry = possible_entry;
00135
00136 return 0;
00137 }
00138
00139 template <ACE_T1> int
00140 ACE_Cached_Connect_Strategy_Ex<ACE_T2>::find_or_create_svc_handler_i
00141 (SVC_HANDLER *&sh,
00142 const ACE_PEER_CONNECTOR_ADDR &remote_addr,
00143 ACE_Time_Value *timeout,
00144 const ACE_PEER_CONNECTOR_ADDR &local_addr,
00145 int reuse_addr,
00146 int flags,
00147 int perms,
00148 ACE_Hash_Map_Entry<ACE_Refcounted_Hash_Recyclable<ACE_PEER_CONNECTOR_ADDR>, ACE_Pair<SVC_HANDLER *, ATTRIBUTES> > *&entry,
00149 int &found)
00150 {
00151 REFCOUNTED_HASH_RECYCLABLE_ADDRESS search_addr (remote_addr);
00152
00153
00154
00155 while (this->find (search_addr, entry) != -1)
00156 {
00157
00158
00159 sh = entry->int_id_.first ();
00160
00161
00162 int state_result =
00163 ACE::handle_ready (sh->peer ().get_handle (),
00164 &ACE_Time_Value::zero,
00165 1,
00166 0,
00167 1);
00168
00169 if (state_result == 1)
00170 {
00171
00172 if (sh->close () == -1)
00173 return -1;
00174
00175 sh = 0;
00176
00177
00178 }
00179 else if ((state_result == -1) && (errno == ETIME))
00180 {
00181
00182
00183 found = 1;
00184
00185
00186
00187 if (this->prepare_for_recycling (sh) == -1)
00188 return -1;
00189
00190 return 0;
00191 }
00192 else
00193 {
00194 return -1;
00195 }
00196 }
00197
00198
00199
00200
00201 found = 0;
00202
00203
00204
00205
00206
00207
00208
00209
00210 SVC_HANDLER *potential_handler = 0;
00211
00212
00213 if (this->make_svc_handler (potential_handler) == -1)
00214 return -1;
00215
00216
00217 if (this->cached_connect (potential_handler,
00218 remote_addr,
00219 timeout,
00220 local_addr,
00221 reuse_addr,
00222 flags,
00223 perms) == -1)
00224 {
00225
00226 potential_handler->close (0);
00227
00228 return -1;
00229 }
00230 else
00231 {
00232
00233 if (this->connection_cache_.bind (search_addr,
00234 potential_handler,
00235 entry) == -1)
00236 {
00237
00238 potential_handler->close (0);
00239
00240 return -1;
00241 }
00242
00243
00244
00245 sh = potential_handler;
00246
00247
00248
00249 this->assign_recycler (sh, this, entry);
00250 }
00251
00252 return 0;
00253 }
00254
00255 template <ACE_T1> int
00256 ACE_Cached_Connect_Strategy_Ex<ACE_T2>::cached_connect (SVC_HANDLER *&sh,
00257 const ACE_PEER_CONNECTOR_ADDR &remote_addr,
00258 ACE_Time_Value *timeout,
00259 const ACE_PEER_CONNECTOR_ADDR &local_addr,
00260 int reuse_addr,
00261 int flags,
00262 int perms)
00263 {
00264
00265
00266 if (this->new_connection (sh,
00267 remote_addr,
00268 timeout,
00269 local_addr,
00270 reuse_addr,
00271 flags,
00272 perms) == -1)
00273 {
00274
00275
00276
00277
00278
00279
00280 if (errno == EWOULDBLOCK)
00281 errno = ENOTSUP;
00282 else if (ACE::out_of_handles (errno))
00283 {
00284
00285
00286
00287
00288
00289 if (this->purge_connections () == -1)
00290 return -1;
00291
00292
00293 if (this->new_connection (sh,
00294 remote_addr,
00295 timeout,
00296 local_addr,
00297 reuse_addr,
00298 flags,
00299 perms) == -1)
00300 {
00301 if (errno == EWOULDBLOCK)
00302 errno = ENOTSUP;
00303 return -1;
00304 }
00305 }
00306 else
00307 {
00308 return -1;
00309 }
00310 }
00311
00312 return 0;
00313
00314 }
00315
00316
00317 template <ACE_T1> int
00318 ACE_Cached_Connect_Strategy_Ex<ACE_T2>::connect_svc_handler_i
00319 (SVC_HANDLER *&sh,
00320 const ACE_PEER_CONNECTOR_ADDR &remote_addr,
00321 ACE_Time_Value *timeout,
00322 const ACE_PEER_CONNECTOR_ADDR &local_addr,
00323 int reuse_addr,
00324 int flags,
00325 int perms,
00326 int& found)
00327 {
00328 CONNECTION_CACHE_ENTRY *entry = 0;
00329
00330
00331 if (sh != 0)
00332 {
00333
00334 int result = this->check_hint_i (sh,
00335 remote_addr,
00336 timeout,
00337 local_addr,
00338 reuse_addr,
00339 flags,
00340 perms,
00341 entry,
00342 found);
00343 if (result != 0)
00344 return result;
00345 }
00346
00347
00348 if (!found)
00349 {
00350 int result = this->find_or_create_svc_handler_i (sh,
00351 remote_addr,
00352 timeout,
00353 local_addr,
00354 reuse_addr,
00355 flags,
00356 perms,
00357 entry,
00358 found);
00359
00360 if (result != 0)
00361 return result;
00362
00363 }
00364
00365
00366
00367 entry->ext_id_.recycle_state (ACE_RECYCLABLE_BUSY);
00368
00369
00370 entry->ext_id_.increment ();
00371
00372 return 0;
00373 }
00374
00375
00376 template <ACE_T1> int
00377 ACE_Cached_Connect_Strategy_Ex<ACE_T2>::cache_i (const void *recycling_act)
00378 {
00379
00380 CONNECTION_CACHE_ENTRY *entry = (CONNECTION_CACHE_ENTRY *) recycling_act;
00381
00382
00383
00384 entry->ext_id_.recycle_state (ACE_RECYCLABLE_IDLE_AND_PURGABLE);
00385
00386 return 0;
00387 }
00388
00389 template<ACE_T1> int
00390 ACE_Cached_Connect_Strategy_Ex<ACE_T2>::recycle_state_i (const void *recycling_act,
00391 ACE_Recyclable_State new_state)
00392 {
00393
00394 CONNECTION_CACHE_ENTRY *entry = (CONNECTION_CACHE_ENTRY *) recycling_act;
00395
00396
00397
00398 entry->ext_id_.recycle_state (new_state);
00399
00400 return 0;
00401 }
00402
00403 template<ACE_T1> ACE_Recyclable_State
00404 ACE_Cached_Connect_Strategy_Ex<ACE_T2>::recycle_state_i (const void *recycling_act) const
00405 {
00406
00407 CONNECTION_CACHE_ENTRY *entry = (CONNECTION_CACHE_ENTRY *) recycling_act;
00408
00409
00410
00411 return entry->ext_id_.recycle_state ();
00412 }
00413
00414 template <ACE_T1> int
00415 ACE_Cached_Connect_Strategy_Ex<ACE_T2>::purge_i (const void *recycling_act)
00416 {
00417
00418 CONNECTION_CACHE_ENTRY *entry = (CONNECTION_CACHE_ENTRY *) recycling_act;
00419
00420 return this->connection_cache_.unbind (entry);
00421 }
00422
00423
00424 template <ACE_T1> int
00425 ACE_Cached_Connect_Strategy_Ex<ACE_T2>::mark_as_closed_i (const void *recycling_act)
00426 {
00427
00428 CONNECTION_CACHE_ENTRY *entry = (CONNECTION_CACHE_ENTRY *) recycling_act;
00429
00430
00431 entry->ext_id_.recycle_state (ACE_RECYCLABLE_CLOSED);
00432
00433 return 0;
00434 }
00435
00436 template <ACE_T1> int
00437 ACE_Cached_Connect_Strategy_Ex<ACE_T2>::cleanup_hint_i (const void *recycling_act,
00438 void **act_holder)
00439 {
00440
00441
00442 if (act_holder)
00443 *act_holder = 0;
00444
00445
00446 CONNECTION_CACHE_ENTRY *entry = (CONNECTION_CACHE_ENTRY *) recycling_act;
00447
00448
00449 int refcount = entry->ext_id_.decrement ();
00450
00451
00452
00453 if (entry->ext_id_.recycle_state () == ACE_RECYCLABLE_CLOSED &&
00454 refcount == 0)
00455 {
00456 entry->int_id_.first ()->recycler (0, 0);
00457 entry->int_id_.first ()->close ();
00458 this->purge_i (entry);
00459 }
00460
00461 return 0;
00462 }
00463
00464 template <ACE_T1> int
00465 ACE_Cached_Connect_Strategy_Ex<ACE_T2>::purge_connections (void)
00466 {
00467 return this->connection_cache_.purge ();
00468 }
00469
00470 template <ACE_T1> CACHING_STRATEGY &
00471 ACE_Cached_Connect_Strategy_Ex<ACE_T2>::caching_strategy (void)
00472 {
00473 return this->connection_cache_.caching_strategy ();
00474 }
00475
00476 template <ACE_T1> int
00477 ACE_Cached_Connect_Strategy_Ex<ACE_T2>::find (ACE_Refcounted_Hash_Recyclable<ACE_PEER_CONNECTOR_ADDR> &search_addr,
00478 ACE_Hash_Map_Entry<ACE_Refcounted_Hash_Recyclable<ACE_PEER_CONNECTOR_ADDR>, ACE_Pair<SVC_HANDLER *, ATTRIBUTES> > *&entry)
00479 {
00480 typedef ACE_Hash_Map_Bucket_Iterator<REFCOUNTED_HASH_RECYCLABLE_ADDRESS,
00481 ACE_Pair<SVC_HANDLER *, ATTRIBUTES>,
00482 ACE_Hash<REFCOUNTED_HASH_RECYCLABLE_ADDRESS>,
00483 ACE_Equal_To<REFCOUNTED_HASH_RECYCLABLE_ADDRESS>,
00484 ACE_Null_Mutex>
00485 CONNECTION_CACHE_BUCKET_ITERATOR;
00486
00487 CONNECTION_CACHE_BUCKET_ITERATOR iterator (this->connection_cache_.map (),
00488 search_addr);
00489
00490 CONNECTION_CACHE_BUCKET_ITERATOR end (this->connection_cache_.map (),
00491 search_addr,
00492 1);
00493
00494 for (;
00495 iterator != end;
00496 ++iterator)
00497 {
00498 REFCOUNTED_HASH_RECYCLABLE_ADDRESS &addr = (*iterator).ext_id_;
00499
00500 if (addr.recycle_state () != ACE_RECYCLABLE_IDLE_AND_PURGABLE &&
00501 addr.recycle_state () != ACE_RECYCLABLE_IDLE_BUT_NOT_PURGABLE)
00502 continue;
00503
00504 if (addr.subject () != search_addr.subject ())
00505 continue;
00506
00507 entry = &(*iterator);
00508
00509
00510
00511
00512
00513
00514
00515 int find_result = 0;
00516
00517 int result = this->caching_strategy ().notify_find (find_result,
00518 entry->int_id_.second ());
00519
00520 if (result == -1)
00521 return result;
00522
00523 return 0;
00524 }
00525
00526 return -1;
00527 }
00528
00529 template <ACE_T1> void
00530 ACE_Cached_Connect_Strategy_Ex<ACE_T2>::cleanup (void)
00531 {
00532
00533 ACE_GUARD (MUTEX, ace_mon, *this->lock_);
00534
00535 #if defined (ACE_HAS_BROKEN_EXTENDED_TEMPLATES)
00536
00537 typedef ACE_Hash_Map_Iterator_Ex<REFCOUNTED_HASH_RECYCLABLE_ADDRESS,
00538 ACE_Pair<SVC_HANDLER *, ATTRIBUTES>,
00539 ACE_Hash<REFCOUNTED_HASH_RECYCLABLE_ADDRESS>,
00540 ACE_Equal_To<REFCOUNTED_HASH_RECYCLABLE_ADDRESS>,
00541 ACE_Null_Mutex>
00542 CONNECTION_MAP_ITERATOR;
00543
00544
00545 CONNECTION_MAP_ITERATOR iter = this->connection_cache_.map ().begin ();
00546
00547
00548 while (iter != this->connection_cache_.map ().end ())
00549 {
00550 if ((*iter).int_id_.first () != 0)
00551 {
00552
00553 CONNECTION_CACHE_ENTRY *entry = (CONNECTION_CACHE_ENTRY *)
00554 (*iter).int_id_.first ()->recycling_act ();
00555
00556
00557 (*iter).int_id_.first ()->recycler (0, 0);
00558 (*iter).int_id_.first ()->close ();
00559
00560
00561 CONNECTION_MAP_ITERATOR next_iter = iter;
00562 ++next_iter;
00563
00564
00565 this->purge_i (entry);
00566
00567
00568 iter = next_iter;
00569 }
00570 else
00571 ++iter;
00572 }
00573 #else
00574 ACE_TYPENAME CONNECTION_CACHE::ITERATOR iter =
00575 this->connection_cache_.begin ();
00576 while (iter != this->connection_cache_.end ())
00577 {
00578 if ((*iter).second () != 0)
00579 {
00580
00581 CONNECTION_CACHE_ENTRY *entry = (CONNECTION_CACHE_ENTRY *)
00582 (*iter).second ()->recycling_act ();
00583
00584
00585 (*iter).second ()->recycler (0, 0);
00586 (*iter).second ()->close ();
00587
00588
00589 ACE_TYPENAME CONNECTION_CACHE::ITERATOR next_iter = iter;
00590 ++next_iter;
00591
00592
00593 this->purge_i (entry);
00594
00595
00596 iter = next_iter;
00597 }
00598 else
00599 ++iter;
00600 }
00601 #endif
00602
00603 }
00604
00605 ACE_ALLOC_HOOK_DEFINE(ACE_Cached_Connect_Strategy_Ex)
00606
00607
00608 template <ACE_T1>
00609 ACE_Bounded_Cached_Connect_Strategy<ACE_T2>::ACE_Bounded_Cached_Connect_Strategy
00610 (size_t max_size,
00611 CACHING_STRATEGY &caching_s,
00612 ACE_Creation_Strategy<SVC_HANDLER> *cre_s,
00613 ACE_Concurrency_Strategy<SVC_HANDLER> *con_s,
00614 ACE_Recycling_Strategy<SVC_HANDLER> *rec_s,
00615 MUTEX *lock,
00616 int delete_lock)
00617 : CCSEBASE (caching_s, cre_s, con_s, rec_s, lock, delete_lock),
00618 max_size_ (max_size)
00619 {
00620 }
00621
00622 template <ACE_T1>
00623 ACE_Bounded_Cached_Connect_Strategy<ACE_T2>::~ACE_Bounded_Cached_Connect_Strategy(void)
00624 {
00625 }
00626
00627 template <ACE_T1>
00628 int
00629 ACE_Bounded_Cached_Connect_Strategy<ACE_T2>::find_or_create_svc_handler_i
00630 (SVC_HANDLER *&sh,
00631 const ACE_PEER_CONNECTOR_ADDR &remote_addr,
00632 ACE_Time_Value *timeout,
00633 const ACE_PEER_CONNECTOR_ADDR &local_addr,
00634 int reuse_addr,
00635 int flags,
00636 int perms,
00637 ACE_Hash_Map_Entry<ACE_Refcounted_Hash_Recyclable<ACE_PEER_CONNECTOR_ADDR>,
00638 ACE_Pair<SVC_HANDLER *, ATTRIBUTES> > *&entry,
00639 int &found)
00640 {
00641
00642 REFCOUNTED_HASH_RECYCLABLE_ADDRESS search_addr (remote_addr);
00643
00644
00645
00646 while (this->find (search_addr, entry) != -1)
00647 {
00648
00649
00650 sh = entry->int_id_.first ();
00651
00652
00653 int state_result= ACE::handle_ready (sh->peer ().get_handle (),
00654 &ACE_Time_Value::zero,
00655 1,
00656 0,
00657 1);
00658
00659 if (state_result == 1)
00660 {
00661
00662
00663 if (sh->close () == -1)
00664 {
00665 ACE_ASSERT (0);
00666 return -1;
00667 }
00668 sh = 0;
00669
00670 }
00671 else if ((state_result == -1) && (errno == ETIME))
00672 {
00673
00674
00675 found = 1;
00676
00677
00678
00679 if (this->prepare_for_recycling (sh) == -1)
00680 {
00681 ACE_ASSERT (0);
00682 return -1;
00683 }
00684
00685 return 0;
00686 }
00687 else
00688 {
00689 ACE_ASSERT (0);
00690
00691 ACE_ERROR ((LM_ERROR,
00692 ACE_LIB_TEXT ("(%t)ACE_Bounded_Cached_Connect_Strategy<>::")
00693 ACE_LIB_TEXT ("find_or_create_svc_handler_i - ")
00694 ACE_LIB_TEXT ("error polling server socket state.\n")));
00695
00696 return -1;
00697 }
00698 }
00699
00700
00701
00702
00703 found = 0;
00704
00705
00706 if ((this->max_size_ > 0) &&
00707 (this->connection_cache_.current_size () >= this->max_size_))
00708 {
00709
00710 if (this->purge_connections () == -1)
00711 return -1;
00712
00713
00714 if (this->connection_cache_.current_size () >= this->max_size_)
00715
00716 return -1;
00717
00718
00719 }
00720
00721
00722
00723
00724
00725
00726
00727
00728 SVC_HANDLER *potential_handler = 0;
00729
00730
00731 if (this->make_svc_handler (potential_handler) == -1)
00732 return -1;
00733
00734
00735 if (this->cached_connect (potential_handler,
00736 remote_addr,
00737 timeout,
00738 local_addr,
00739 reuse_addr,
00740 flags,
00741 perms) == -1)
00742 {
00743
00744 potential_handler->close (0);
00745 return -1;
00746 }
00747 else
00748 {
00749
00750 if (this->connection_cache_.bind (search_addr,
00751 potential_handler,
00752 entry) == -1)
00753 {
00754
00755 potential_handler->close (0);
00756
00757 return -1;
00758 }
00759
00760
00761
00762 sh = potential_handler;
00763
00764
00765 this->assign_recycler (sh, this, entry);
00766 }
00767
00768 return 0;
00769 }
00770
00771 ACE_ALLOC_HOOK_DEFINE(ACE_Bounded_Cached_Connect_Strategy)
00772
00773 #undef ACE_T1
00774 #undef ACE_T2
00775
00776 #endif