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