Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

Cached_Connect_Strategy_T.cpp

Go to the documentation of this file.
00001 #include "ace_pch.h"
00002 //$Id: Cached_Connect_Strategy_T.cpp,v 1.1.1.3.64.1 2003/03/13 19:44:20 chad Exp $
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 /* ACE_LACKS_PRAGMA_ONCE */
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   // Get the recycling act for the svc_handler
00072   CONNECTION_CACHE_ENTRY *possible_entry = (CONNECTION_CACHE_ENTRY *) sh->recycling_act ();
00073 
00074   // Check to see if the hint svc_handler has been closed down
00075   if (possible_entry->ext_id_.recycle_state () == ACE_RECYCLABLE_CLOSED)
00076     {
00077       // If close, decrement refcount
00078       if (possible_entry->ext_id_.decrement () == 0)
00079         {
00080           // If refcount goes to zero, close down the svc_handler
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       // Hint not successful
00087       found = 0;
00088 
00089       // Reset hint
00090       sh = 0;
00091     }
00092 
00093   // If hint is not closed, see if it is connected to the correct
00094   // address and is recyclable
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       // Hint successful
00100       found = 1;
00101 
00102       // Tell the <svc_handler> that it should prepare itself for
00103       // being recycled.
00104       this->prepare_for_recycling (sh);
00105 
00106       //
00107       // Update the caching attributes directly since we don't do a
00108       // find() on the cache map.
00109       //
00110 
00111       // Indicates successful find.
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       // This hint will not be used.
00123       possible_entry->ext_id_.decrement ();
00124 
00125       // Hint not successful
00126       found = 0;
00127 
00128       // If <sh> is not connected to the correct address or is busy,
00129       // we will not use it.
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   // Try to find the address in the cache.  Only if we don't find it
00154   // do we create a new <SVC_HANDLER> and connect it with the server.
00155   while (this->find (search_addr, entry) != -1)
00156   {
00157     // We found a cached svc_handler.
00158     // Get the cached <svc_handler>
00159     sh = entry->int_id_.first ();
00160 
00161     // Is the connection clean?
00162     int state_result =
00163       ACE::handle_ready (sh->peer ().get_handle (),
00164                          &ACE_Time_Value::zero,
00165                          1, // read ready
00166                          0, // write ready
00167                          1);// exception ready
00168 
00169     if (state_result == 1)
00170     {
00171 
00172       if (sh->close () == -1)
00173         return -1;
00174 
00175       sh = 0;
00176 
00177       // Cycle it once again..
00178     }
00179     else if ((state_result == -1) && (errno == ETIME))
00180     {
00181       // Found!!!
00182       // Set the flag
00183       found = 1;
00184 
00185       // Tell the <svc_handler> that it should prepare itself for
00186       // being recycled.
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   // Not found...
00199 
00200   // Set the flag
00201   found = 0;
00202 
00203   // We need to use a temporary variable here since we are not
00204   // allowed to change <sh> because other threads may use this
00205   // when we let go of the lock during the OS level connect.
00206   //
00207   // Note that making a new svc_handler, connecting remotely,
00208   // binding to the map, and assigning of the hint and recycler
00209   // should be atomic to the outside world.
00210   SVC_HANDLER *potential_handler = 0;
00211 
00212   // Create a new svc_handler
00213   if (this->make_svc_handler (potential_handler) == -1)
00214     return -1;
00215 
00216   // Connect using the svc_handler.
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       // Close the svc handler.
00226       potential_handler->close (0);
00227 
00228       return -1;
00229     }
00230     else
00231     {
00232       // Insert the new SVC_HANDLER instance into the cache.
00233       if (this->connection_cache_.bind (search_addr,
00234                                         potential_handler,
00235                                         entry) == -1)
00236         {
00237           // Close the svc handler and reset <sh>.
00238           potential_handler->close (0);
00239 
00240           return -1;
00241         }
00242 
00243       // Everything succeeded as planned. Assign <sh> to
00244       // <potential_handler>.
00245       sh = potential_handler;
00246 
00247       // Set the recycler and the recycling act
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   // Actively establish the connection.  This is a timed blocking
00265   // connect.
00266   if (this->new_connection (sh,
00267                             remote_addr,
00268                             timeout,
00269                             local_addr,
00270                             reuse_addr,
00271                             flags,
00272                             perms) == -1)
00273     {
00274       // If connect() failed because of timeouts, we have to reject
00275       // the connection entirely. This is necessary since currently
00276       // there is no way for the non-blocking connects to complete and
00277       // for the <Connector> to notify the cache of the completion of
00278       // connect().
00279 
00280       if (errno == EWOULDBLOCK)
00281         errno = ENOTSUP;
00282       else if (ACE::out_of_handles (errno))
00283         {
00284           // If the connect failed due to the process running out of
00285           // file descriptors then, auto_purging of some connections
00286           // are done from the CONNECTION_CACHE. This frees the
00287           // descriptors which get used in the connect process and
00288           // hence the same method is called again!
00289           if (this->purge_connections () == -1)
00290             return -1;
00291 
00292           // Try connecting again.
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   // Check if the user passed a hint svc_handler
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   // If not found
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   // For all successful cases: mark the <svc_handler> in the cache
00366   // as being <in_use>.  Therefore recyclable is BUSY.
00367   entry->ext_id_.recycle_state (ACE_RECYCLABLE_BUSY);
00368 
00369   // And increment the refcount
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   // The wonders and perils of ACT
00380   CONNECTION_CACHE_ENTRY *entry = (CONNECTION_CACHE_ENTRY *) recycling_act;
00381 
00382   // Mark the <svc_handler> in the cache as not being <in_use>.
00383   // Therefore recyclable is IDLE.
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   // The wonders and perils of ACT
00394   CONNECTION_CACHE_ENTRY *entry = (CONNECTION_CACHE_ENTRY *) recycling_act;
00395 
00396   // Mark the <svc_handler> in the cache as not being <in_use>.
00397   // Therefore recyclable is IDLE.
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   // The wonders and perils of ACT
00407   CONNECTION_CACHE_ENTRY *entry = (CONNECTION_CACHE_ENTRY *) recycling_act;
00408 
00409   // Mark the <svc_handler> in the cache as not being <in_use>.
00410   // Therefore recyclable is IDLE.
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   // The wonders and perils of ACT
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   // The wonders and perils of ACT
00428   CONNECTION_CACHE_ENTRY *entry = (CONNECTION_CACHE_ENTRY *) recycling_act;
00429 
00430   // Mark the <svc_handler> in the cache as CLOSED.
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   // Reset the <*act_holder> in the confines and protection of the
00441   // lock.
00442   if (act_holder)
00443     *act_holder = 0;
00444 
00445   // The wonders and perils of ACT
00446   CONNECTION_CACHE_ENTRY *entry = (CONNECTION_CACHE_ENTRY *) recycling_act;
00447 
00448   // Decrement the refcount on the <svc_handler>.
00449   int refcount = entry->ext_id_.decrement ();
00450 
00451   // If the svc_handler state is closed and the refcount == 0, call
00452   // close() on svc_handler.
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       // Update the caching attributes directly since we don't do a
00511       // find() on the cache map.
00512       //
00513 
00514       // Indicates successful find.
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   // Excluded other threads from changing the cache while we cleanup
00533   ACE_GUARD (MUTEX, ace_mon, *this->lock_);
00534   // Close down all cached service handlers.
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   // CONNECTION_MAP_ITERATOR end = this->connection_cache_.map ().end ();
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          // save entry for future use
00553          CONNECTION_CACHE_ENTRY *entry = (CONNECTION_CACHE_ENTRY *)
00554            (*iter).int_id_.first ()->recycling_act ();
00555 
00556          // close handler
00557          (*iter).int_id_.first ()->recycler (0, 0);
00558          (*iter).int_id_.first ()->close ();
00559 
00560          // remember next iter
00561          CONNECTION_MAP_ITERATOR next_iter = iter;
00562          ++next_iter;
00563 
00564          // purge the item from the hash
00565          this->purge_i (entry);
00566 
00567          // assign next iter
00568          iter  = next_iter;
00569      }
00570      else
00571        ++iter;
00572    }
00573 #else  /* ACE_HAS_BROKEN_EXTENDED_TEMPLATES */
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           // save entry for future use
00581           CONNECTION_CACHE_ENTRY *entry = (CONNECTION_CACHE_ENTRY *)
00582             (*iter).second ()->recycling_act ();
00583 
00584           // close handler
00585           (*iter).second ()->recycler (0, 0);
00586           (*iter).second ()->close ();
00587 
00588           // remember next iter
00589           ACE_TYPENAME CONNECTION_CACHE::ITERATOR next_iter = iter;
00590           ++next_iter;
00591 
00592           // purge the item from the hash
00593           this->purge_i (entry);
00594 
00595           // assign next iter
00596           iter  = next_iter;
00597         }
00598      else
00599        ++iter;
00600     }
00601 #endif /* ACE_HAS_BROKEN_EXTENDED_TEMPLATES */
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   // Try to find the address in the cache.  Only if we don't find it
00645   // do we create a new <SVC_HANDLER> and connect it with the server.
00646   while (this->find (search_addr, entry) != -1)
00647     {
00648       // We found a cached svc_handler.
00649       // Get the cached <svc_handler>
00650       sh = entry->int_id_.first ();
00651 
00652       // Is the connection clean?
00653       int state_result= ACE::handle_ready (sh->peer ().get_handle (),
00654                                            &ACE_Time_Value::zero,
00655                                            1, // read ready
00656                                            0, // write ready
00657                                            1);// exception ready
00658 
00659       if (state_result == 1)
00660         {
00661           // The connection was disconnected during idle.
00662           // close the svc_handler down.
00663           if (sh->close () == -1)
00664             {
00665               ACE_ASSERT (0);
00666               return -1;
00667             }
00668           sh = 0;
00669           // and rotate once more...
00670         }
00671       else if ((state_result == -1) && (errno == ETIME))
00672         {
00673           // Found!!!
00674           // Set the flag
00675           found = 1;
00676 
00677           // Tell the <svc_handler> that it should prepare itself for
00678           // being recycled.
00679           if (this->prepare_for_recycling (sh) == -1)
00680             {
00681               ACE_ASSERT (0);
00682               return -1;
00683             }
00684 
00685           return 0;
00686         }
00687       else  // some other return value or error...
00688         {
00689           ACE_ASSERT (0); // just to see it coming
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   // Not found...
00701 
00702   // Set the flag
00703   found = 0;
00704 
00705   // Check the limit of handlers...
00706   if ((this->max_size_ > 0) &&
00707       (this->connection_cache_.current_size () >= this->max_size_))
00708     {
00709       // Try to purge idle connections
00710       if (this->purge_connections () == -1)
00711         return -1;
00712 
00713       // Check limit again.
00714       if (this->connection_cache_.current_size () >= this->max_size_)
00715         // still too much!
00716         return -1;
00717 
00718       // OK, we have room now...
00719     }
00720 
00721   // We need to use a temporary variable here since we are not
00722   // allowed to change <sh> because other threads may use this
00723   // when we let go of the lock during the OS level connect.
00724   //
00725   // Note that making a new svc_handler, connecting remotely,
00726   // binding to the map, and assigning of the hint and recycler
00727   // should be atomic to the outside world.
00728   SVC_HANDLER *potential_handler = 0;
00729 
00730   // Create a new svc_handler
00731   if (this->make_svc_handler (potential_handler) == -1)
00732     return -1;
00733 
00734   // Connect using the svc_handler.
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       // Close the svc handler.
00744       potential_handler->close (0);
00745       return -1;
00746     }
00747   else
00748     {
00749       // Insert the new SVC_HANDLER instance into the cache.
00750       if (this->connection_cache_.bind (search_addr,
00751                                         potential_handler,
00752                                         entry) == -1)
00753         {
00754           // Close the svc handler and reset <sh>.
00755           potential_handler->close (0);
00756 
00757           return -1;
00758         }
00759 
00760       // Everything succeeded as planned. Assign <sh> to
00761       // <potential_handler>.
00762       sh = potential_handler;
00763 
00764       // Set the recycler and the recycling act
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 /* CACHED_CONNECT_STRATEGY_T_C */

Generated on Mon Jun 16 11:19:16 2003 for ACE by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002