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_LIB_TEXT ("%p\n"),
00038 ACE_LIB_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 = (CONNECTION_CACHE_ENTRY *) sh->recycling_act ();
00071
00072
00073 if (possible_entry->ext_id_.recycle_state () == ACE_RECYCLABLE_CLOSED)
00074 {
00075
00076 if (possible_entry->ext_id_.decrement () == 0)
00077 {
00078
00079 possible_entry->int_id_.first ()->recycler (0, 0);
00080 possible_entry->int_id_.first ()->close ();
00081 this->purge_i (possible_entry);
00082 }
00083
00084
00085 found = 0;
00086
00087
00088 sh = 0;
00089 }
00090
00091
00092
00093 else if ((possible_entry->ext_id_.recycle_state () == ACE_RECYCLABLE_IDLE_AND_PURGABLE ||
00094 possible_entry->ext_id_.recycle_state () == ACE_RECYCLABLE_IDLE_BUT_NOT_PURGABLE) &&
00095 possible_entry->ext_id_.subject () == remote_addr)
00096 {
00097
00098 found = 1;
00099
00100
00101
00102 this->prepare_for_recycling (sh);
00103
00104
00105
00106
00107
00108
00109
00110 int find_result = 0;
00111
00112 int result = this->caching_strategy ().notify_find (find_result,
00113 possible_entry->int_id_.second ());
00114
00115 if (result == -1)
00116 return result;
00117 }
00118 else
00119 {
00120
00121 possible_entry->ext_id_.decrement ();
00122
00123
00124 found = 0;
00125
00126
00127
00128 sh = 0;
00129 }
00130
00131 if (found)
00132 entry = possible_entry;
00133
00134 return 0;
00135 }
00136
00137 template <ACE_T1> int
00138 ACE_Cached_Connect_Strategy_Ex<ACE_T2>::find_or_create_svc_handler_i
00139 (SVC_HANDLER *&sh,
00140 const ACE_PEER_CONNECTOR_ADDR &remote_addr,
00141 ACE_Time_Value *timeout,
00142 const ACE_PEER_CONNECTOR_ADDR &local_addr,
00143 int reuse_addr,
00144 int flags,
00145 int perms,
00146 ACE_Hash_Map_Entry<ACE_Refcounted_Hash_Recyclable<ACE_PEER_CONNECTOR_ADDR>, ACE_Pair<SVC_HANDLER *, ATTRIBUTES> > *&entry,
00147 int &found)
00148 {
00149 REFCOUNTED_HASH_RECYCLABLE_ADDRESS search_addr (remote_addr);
00150
00151
00152
00153 while (this->find (search_addr, entry) != -1)
00154 {
00155
00156
00157 sh = entry->int_id_.first ();
00158
00159
00160 int state_result =
00161 ACE::handle_ready (sh->peer ().get_handle (),
00162 &ACE_Time_Value::zero,
00163 1,
00164 0,
00165 1);
00166
00167 if (state_result == 1)
00168 {
00169
00170 if (sh->close () == -1)
00171 return -1;
00172
00173 sh = 0;
00174
00175
00176 }
00177 else if ((state_result == -1) && (errno == ETIME))
00178 {
00179
00180
00181 found = 1;
00182
00183
00184
00185 if (this->prepare_for_recycling (sh) == -1)
00186 return -1;
00187
00188 return 0;
00189 }
00190 else
00191 {
00192 return -1;
00193 }
00194 }
00195
00196
00197
00198
00199 found = 0;
00200
00201
00202
00203
00204
00205
00206
00207
00208 SVC_HANDLER *potential_handler = 0;
00209
00210
00211 if (this->make_svc_handler (potential_handler) == -1)
00212 return -1;
00213
00214
00215 if (this->cached_connect (potential_handler,
00216 remote_addr,
00217 timeout,
00218 local_addr,
00219 reuse_addr,
00220 flags,
00221 perms) == -1)
00222 {
00223
00224 potential_handler->close (0);
00225
00226 return -1;
00227 }
00228 else
00229 {
00230
00231 if (this->connection_cache_.bind (search_addr,
00232 potential_handler,
00233 entry) == -1)
00234 {
00235
00236 potential_handler->close (0);
00237
00238 return -1;
00239 }
00240
00241
00242
00243 sh = potential_handler;
00244
00245
00246
00247 this->assign_recycler (sh, this, entry);
00248 }
00249
00250 return 0;
00251 }
00252
00253 template <ACE_T1> int
00254 ACE_Cached_Connect_Strategy_Ex<ACE_T2>::cached_connect (SVC_HANDLER *&sh,
00255 const ACE_PEER_CONNECTOR_ADDR &remote_addr,
00256 ACE_Time_Value *timeout,
00257 const ACE_PEER_CONNECTOR_ADDR &local_addr,
00258 int reuse_addr,
00259 int flags,
00260 int perms)
00261 {
00262
00263
00264 if (this->new_connection (sh,
00265 remote_addr,
00266 timeout,
00267 local_addr,
00268 reuse_addr,
00269 flags,
00270 perms) == -1)
00271 {
00272
00273
00274
00275
00276
00277
00278 if (errno == EWOULDBLOCK || errno == ETIMEDOUT)
00279 errno = ENOTSUP;
00280 else if (ACE::out_of_handles (errno) || errno == EADDRINUSE)
00281 {
00282
00283
00284
00285
00286
00287 if (this->purge_connections () == -1)
00288 return -1;
00289
00290
00291 if (this->new_connection (sh,
00292 remote_addr,
00293 timeout,
00294 local_addr,
00295 reuse_addr,
00296 flags,
00297 perms) == -1)
00298 {
00299 if (errno == EWOULDBLOCK || errno == ETIMEDOUT)
00300 errno = ENOTSUP;
00301 return -1;
00302 }
00303 }
00304 else
00305 {
00306 return -1;
00307 }
00308 }
00309
00310 return 0;
00311
00312 }
00313
00314
00315 template <ACE_T1> int
00316 ACE_Cached_Connect_Strategy_Ex<ACE_T2>::connect_svc_handler_i
00317 (SVC_HANDLER *&sh,
00318 const ACE_PEER_CONNECTOR_ADDR &remote_addr,
00319 ACE_Time_Value *timeout,
00320 const ACE_PEER_CONNECTOR_ADDR &local_addr,
00321 int reuse_addr,
00322 int flags,
00323 int perms,
00324 int& found)
00325 {
00326 CONNECTION_CACHE_ENTRY *entry = 0;
00327
00328
00329 if (sh != 0)
00330 {
00331 int result = this->check_hint_i (sh,
00332 remote_addr,
00333 timeout,
00334 local_addr,
00335 reuse_addr,
00336 flags,
00337 perms,
00338 entry,
00339 found);
00340 if (result != 0)
00341 return result;
00342 }
00343
00344
00345 if (!found)
00346 {
00347 int result = this->find_or_create_svc_handler_i (sh,
00348 remote_addr,
00349 timeout,
00350 local_addr,
00351 reuse_addr,
00352 flags,
00353 perms,
00354 entry,
00355 found);
00356
00357 if (result != 0)
00358 return result;
00359
00360
00361 entry->ext_id_.increment ();
00362 }
00363
00364
00365
00366 entry->ext_id_.recycle_state (ACE_RECYCLABLE_BUSY);
00367
00368 return 0;
00369 }
00370
00371
00372 template <ACE_T1> int
00373 ACE_Cached_Connect_Strategy_Ex<ACE_T2>::cache_i (const void *recycling_act)
00374 {
00375
00376 CONNECTION_CACHE_ENTRY *entry = (CONNECTION_CACHE_ENTRY *) recycling_act;
00377
00378
00379
00380 entry->ext_id_.recycle_state (ACE_RECYCLABLE_IDLE_AND_PURGABLE);
00381
00382 return 0;
00383 }
00384
00385 template<ACE_T1> int
00386 ACE_Cached_Connect_Strategy_Ex<ACE_T2>::recycle_state_i (const void *recycling_act,
00387 ACE_Recyclable_State new_state)
00388 {
00389
00390 CONNECTION_CACHE_ENTRY *entry = (CONNECTION_CACHE_ENTRY *) recycling_act;
00391
00392
00393
00394 entry->ext_id_.recycle_state (new_state);
00395
00396 return 0;
00397 }
00398
00399 template<ACE_T1> ACE_Recyclable_State
00400 ACE_Cached_Connect_Strategy_Ex<ACE_T2>::recycle_state_i (const void *recycling_act) const
00401 {
00402
00403 CONNECTION_CACHE_ENTRY *entry = (CONNECTION_CACHE_ENTRY *) recycling_act;
00404
00405
00406
00407 return entry->ext_id_.recycle_state ();
00408 }
00409
00410 template <ACE_T1> int
00411 ACE_Cached_Connect_Strategy_Ex<ACE_T2>::purge_i (const void *recycling_act)
00412 {
00413
00414 CONNECTION_CACHE_ENTRY *entry = (CONNECTION_CACHE_ENTRY *) recycling_act;
00415
00416 return this->connection_cache_.unbind (entry);
00417 }
00418
00419
00420 template <ACE_T1> int
00421 ACE_Cached_Connect_Strategy_Ex<ACE_T2>::mark_as_closed_i (const void *recycling_act)
00422 {
00423
00424 CONNECTION_CACHE_ENTRY *entry = (CONNECTION_CACHE_ENTRY *) recycling_act;
00425
00426
00427 entry->ext_id_.recycle_state (ACE_RECYCLABLE_CLOSED);
00428
00429 return 0;
00430 }
00431
00432 template <ACE_T1> int
00433 ACE_Cached_Connect_Strategy_Ex<ACE_T2>::cleanup_hint_i (const void *recycling_act,
00434 void **act_holder)
00435 {
00436
00437
00438 if (act_holder)
00439 *act_holder = 0;
00440
00441
00442 CONNECTION_CACHE_ENTRY *entry = (CONNECTION_CACHE_ENTRY *) recycling_act;
00443
00444
00445 int refcount = entry->ext_id_.decrement ();
00446
00447
00448
00449 if (entry->ext_id_.recycle_state () == ACE_RECYCLABLE_CLOSED &&
00450 refcount == 0)
00451 {
00452 entry->int_id_.first ()->recycler (0, 0);
00453 entry->int_id_.first ()->close ();
00454 this->purge_i (entry);
00455 }
00456
00457 return 0;
00458 }
00459
00460 template <ACE_T1> int
00461 ACE_Cached_Connect_Strategy_Ex<ACE_T2>::purge_connections (void)
00462 {
00463 return this->connection_cache_.purge ();
00464 }
00465
00466 template <ACE_T1> CACHING_STRATEGY &
00467 ACE_Cached_Connect_Strategy_Ex<ACE_T2>::caching_strategy (void)
00468 {
00469 return this->connection_cache_.caching_strategy ();
00470 }
00471
00472 template <ACE_T1> int
00473 ACE_Cached_Connect_Strategy_Ex<ACE_T2>::find (ACE_Refcounted_Hash_Recyclable<ACE_PEER_CONNECTOR_ADDR> &search_addr,
00474 ACE_Hash_Map_Entry<ACE_Refcounted_Hash_Recyclable<ACE_PEER_CONNECTOR_ADDR>, ACE_Pair<SVC_HANDLER *, ATTRIBUTES> > *&entry)
00475 {
00476 typedef ACE_Hash_Map_Bucket_Iterator<REFCOUNTED_HASH_RECYCLABLE_ADDRESS,
00477 ACE_Pair<SVC_HANDLER *, ATTRIBUTES>,
00478 ACE_Hash<REFCOUNTED_HASH_RECYCLABLE_ADDRESS>,
00479 ACE_Equal_To<REFCOUNTED_HASH_RECYCLABLE_ADDRESS>,
00480 ACE_Null_Mutex>
00481 CONNECTION_CACHE_BUCKET_ITERATOR;
00482
00483 CONNECTION_CACHE_BUCKET_ITERATOR iterator (this->connection_cache_.map (),
00484 search_addr);
00485
00486 CONNECTION_CACHE_BUCKET_ITERATOR end (this->connection_cache_.map (),
00487 search_addr,
00488 1);
00489
00490 for (;
00491 iterator != end;
00492 ++iterator)
00493 {
00494 REFCOUNTED_HASH_RECYCLABLE_ADDRESS &addr = (*iterator).ext_id_;
00495
00496 if (addr.recycle_state () != ACE_RECYCLABLE_IDLE_AND_PURGABLE &&
00497 addr.recycle_state () != ACE_RECYCLABLE_IDLE_BUT_NOT_PURGABLE)
00498 continue;
00499
00500 if (addr.subject () != search_addr.subject ())
00501 continue;
00502
00503 entry = &(*iterator);
00504
00505
00506
00507
00508
00509
00510
00511 int find_result = 0;
00512
00513 int result = this->caching_strategy ().notify_find (find_result,
00514 entry->int_id_.second ());
00515
00516 if (result == -1)
00517 return result;
00518
00519 return 0;
00520 }
00521
00522 return -1;
00523 }
00524
00525 template <ACE_T1> void
00526 ACE_Cached_Connect_Strategy_Ex<ACE_T2>::cleanup (void)
00527 {
00528
00529 ACE_GUARD (MUTEX, ace_mon, *this->lock_);
00530
00531
00532 ACE_TYPENAME CONNECTION_CACHE::ITERATOR iter =
00533 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 ACE_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_LIB_TEXT ("(%t)ACE_Bounded_Cached_Connect_Strategy<>::")
00649 ACE_LIB_TEXT ("find_or_create_svc_handler_i - ")
00650 ACE_LIB_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