Cached_Connect_Strategy_T.cpp

Go to the documentation of this file.
00001 //Cached_Connect_Strategy_T.cpp,v 4.38 2006/02/09 17:03:20 jtc Exp
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 /* ACE_LACKS_PRAGMA_ONCE */
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   // Get the recycling act for the svc_handler
00070   CONNECTION_CACHE_ENTRY *possible_entry = (CONNECTION_CACHE_ENTRY *) sh->recycling_act ();
00071 
00072   // Check to see if the hint svc_handler has been closed down
00073   if (possible_entry->ext_id_.recycle_state () == ACE_RECYCLABLE_CLOSED)
00074     {
00075       // If close, decrement refcount
00076       if (possible_entry->ext_id_.decrement () == 0)
00077         {
00078           // If refcount goes to zero, close down the svc_handler
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       // Hint not successful
00085       found = 0;
00086 
00087       // Reset hint
00088       sh = 0;
00089     }
00090 
00091   // If hint is not closed, see if it is connected to the correct
00092   // address and is recyclable
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       // Hint successful
00098       found = 1;
00099 
00100       // Tell the <svc_handler> that it should prepare itself for
00101       // being recycled.
00102       this->prepare_for_recycling (sh);
00103 
00104       //
00105       // Update the caching attributes directly since we don't do a
00106       // find() on the cache map.
00107       //
00108 
00109       // Indicates successful find.
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       // This hint will not be used.
00121       possible_entry->ext_id_.decrement ();
00122 
00123       // Hint not successful
00124       found = 0;
00125 
00126       // If <sh> is not connected to the correct address or is busy,
00127       // we will not use it.
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   // Try to find the address in the cache.  Only if we don't find it
00152   // do we create a new <SVC_HANDLER> and connect it with the server.
00153   while (this->find (search_addr, entry) != -1)
00154   {
00155     // We found a cached svc_handler.
00156     // Get the cached <svc_handler>
00157     sh = entry->int_id_.first ();
00158 
00159     // Is the connection clean?
00160     int state_result =
00161       ACE::handle_ready (sh->peer ().get_handle (),
00162                          &ACE_Time_Value::zero,
00163                          1, // read ready
00164                          0, // write ready
00165                          1);// exception ready
00166 
00167     if (state_result == 1)
00168     {
00169 
00170       if (sh->close () == -1)
00171         return -1;
00172 
00173       sh = 0;
00174 
00175       // Cycle it once again..
00176     }
00177     else if ((state_result == -1) && (errno == ETIME))
00178     {
00179       // Found!!!
00180       // Set the flag
00181       found = 1;
00182 
00183       // Tell the <svc_handler> that it should prepare itself for
00184       // being recycled.
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   // Not found...
00197 
00198   // Set the flag
00199   found = 0;
00200 
00201   // We need to use a temporary variable here since we are not
00202   // allowed to change <sh> because other threads may use this
00203   // when we let go of the lock during the OS level connect.
00204   //
00205   // Note that making a new svc_handler, connecting remotely,
00206   // binding to the map, and assigning of the hint and recycler
00207   // should be atomic to the outside world.
00208   SVC_HANDLER *potential_handler = 0;
00209 
00210   // Create a new svc_handler
00211   if (this->make_svc_handler (potential_handler) == -1)
00212     return -1;
00213 
00214   // Connect using the svc_handler.
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       // Close the svc handler.
00224       potential_handler->close (0);
00225 
00226       return -1;
00227     }
00228     else
00229     {
00230       // Insert the new SVC_HANDLER instance into the cache.
00231       if (this->connection_cache_.bind (search_addr,
00232                                         potential_handler,
00233                                         entry) == -1)
00234         {
00235           // Close the svc handler and reset <sh>.
00236           potential_handler->close (0);
00237 
00238           return -1;
00239         }
00240 
00241       // Everything succeeded as planned. Assign <sh> to
00242       // <potential_handler>.
00243       sh = potential_handler;
00244 
00245       // Set the recycler and the recycling act
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   // Actively establish the connection.  This is a timed blocking
00263   // connect.
00264   if (this->new_connection (sh,
00265                             remote_addr,
00266                             timeout,
00267                             local_addr,
00268                             reuse_addr,
00269                             flags,
00270                             perms) == -1)
00271     {
00272       // If connect() failed because of timeouts, we have to reject
00273       // the connection entirely. This is necessary since currently
00274       // there is no way for the non-blocking connects to complete and
00275       // for the <Connector> to notify the cache of the completion of
00276       // connect().
00277 
00278       if (errno == EWOULDBLOCK || errno == ETIMEDOUT)
00279         errno = ENOTSUP;
00280       else if (ACE::out_of_handles (errno) || errno == EADDRINUSE)
00281         {
00282           // If the connect failed due to the process running out of
00283           // file descriptors then, auto_purging of some connections
00284           // are done from the CONNECTION_CACHE. This frees the
00285           // descriptors which get used in the connect process and
00286           // hence the same method is called again!
00287           if (this->purge_connections () == -1)
00288             return -1;
00289 
00290           // Try connecting again.
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   // Check if the user passed a hint svc_handler
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   // If not found
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       // Increment the refcount
00361       entry->ext_id_.increment ();
00362     }
00363 
00364   // For all successful cases: mark the <svc_handler> in the cache
00365   // as being <in_use>.  Therefore recyclable is BUSY.
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   // The wonders and perils of ACT
00376   CONNECTION_CACHE_ENTRY *entry = (CONNECTION_CACHE_ENTRY *) recycling_act;
00377 
00378   // Mark the <svc_handler> in the cache as not being <in_use>.
00379   // Therefore recyclable is IDLE.
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   // The wonders and perils of ACT
00390   CONNECTION_CACHE_ENTRY *entry = (CONNECTION_CACHE_ENTRY *) recycling_act;
00391 
00392   // Mark the <svc_handler> in the cache as not being <in_use>.
00393   // Therefore recyclable is IDLE.
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   // The wonders and perils of ACT
00403   CONNECTION_CACHE_ENTRY *entry = (CONNECTION_CACHE_ENTRY *) recycling_act;
00404 
00405   // Mark the <svc_handler> in the cache as not being <in_use>.
00406   // Therefore recyclable is IDLE.
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   // The wonders and perils of ACT
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   // The wonders and perils of ACT
00424   CONNECTION_CACHE_ENTRY *entry = (CONNECTION_CACHE_ENTRY *) recycling_act;
00425 
00426   // Mark the <svc_handler> in the cache as CLOSED.
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   // Reset the <*act_holder> in the confines and protection of the
00437   // lock.
00438   if (act_holder)
00439     *act_holder = 0;
00440 
00441   // The wonders and perils of ACT
00442   CONNECTION_CACHE_ENTRY *entry = (CONNECTION_CACHE_ENTRY *) recycling_act;
00443 
00444   // Decrement the refcount on the <svc_handler>.
00445   int refcount = entry->ext_id_.decrement ();
00446 
00447   // If the svc_handler state is closed and the refcount == 0, call
00448   // close() on svc_handler.
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       // Update the caching attributes directly since we don't do a
00507       // find() on the cache map.
00508       //
00509 
00510       // Indicates successful find.
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   // Excluded other threads from changing the cache while we cleanup
00529   ACE_GUARD (MUTEX, ace_mon, *this->lock_);
00530 
00531   // Close down all cached service handlers.
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           // save entry for future use
00539           CONNECTION_CACHE_ENTRY *entry = (CONNECTION_CACHE_ENTRY *)
00540             (*iter).second ()->recycling_act ();
00541 
00542           // close handler
00543           (*iter).second ()->recycler (0, 0);
00544           (*iter).second ()->close ();
00545 
00546           // remember next iter
00547           ACE_TYPENAME CONNECTION_CACHE::ITERATOR next_iter = iter;
00548           ++next_iter;
00549 
00550           // purge the item from the hash
00551           this->purge_i (entry);
00552 
00553           // assign next iter
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   // Try to find the address in the cache.  Only if we don't find it
00601   // do we create a new <SVC_HANDLER> and connect it with the server.
00602   while (this->find (search_addr, entry) != -1)
00603     {
00604       // We found a cached svc_handler.
00605       // Get the cached <svc_handler>
00606       sh = entry->int_id_.first ();
00607 
00608       // Is the connection clean?
00609       int state_result= ACE::handle_ready (sh->peer ().get_handle (),
00610                                            &ACE_Time_Value::zero,
00611                                            1, // read ready
00612                                            0, // write ready
00613                                            1);// exception ready
00614 
00615       if (state_result == 1)
00616         {
00617           // The connection was disconnected during idle.
00618           // close the svc_handler down.
00619           if (sh->close () == -1)
00620             {
00621               ACE_ASSERT (0);
00622               return -1;
00623             }
00624           sh = 0;
00625           // and rotate once more...
00626         }
00627       else if ((state_result == -1) && (errno == ETIME))
00628         {
00629           // Found!!!
00630           // Set the flag
00631           found = 1;
00632 
00633           // Tell the <svc_handler> that it should prepare itself for
00634           // being recycled.
00635           if (this->prepare_for_recycling (sh) == -1)
00636             {
00637               ACE_ASSERT (0);
00638               return -1;
00639             }
00640 
00641           return 0;
00642         }
00643       else  // some other return value or error...
00644         {
00645           ACE_ASSERT (0); // just to see it coming
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   // Not found...
00657 
00658   // Set the flag
00659   found = 0;
00660 
00661   // Check the limit of handlers...
00662   if ((this->max_size_ > 0) &&
00663       (this->connection_cache_.current_size () >= this->max_size_))
00664     {
00665       // Try to purge idle connections
00666       if (this->purge_connections () == -1)
00667         return -1;
00668 
00669       // Check limit again.
00670       if (this->connection_cache_.current_size () >= this->max_size_)
00671         // still too much!
00672         return -1;
00673 
00674       // OK, we have room now...
00675     }
00676 
00677   // We need to use a temporary variable here since we are not
00678   // allowed to change <sh> because other threads may use this
00679   // when we let go of the lock during the OS level connect.
00680   //
00681   // Note that making a new svc_handler, connecting remotely,
00682   // binding to the map, and assigning of the hint and recycler
00683   // should be atomic to the outside world.
00684   SVC_HANDLER *potential_handler = 0;
00685 
00686   // Create a new svc_handler
00687   if (this->make_svc_handler (potential_handler) == -1)
00688     return -1;
00689 
00690   // Connect using the svc_handler.
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       // Close the svc handler.
00700       potential_handler->close (0);
00701       return -1;
00702     }
00703   else
00704     {
00705       // Insert the new SVC_HANDLER instance into the cache.
00706       if (this->connection_cache_.bind (search_addr,
00707                                         potential_handler,
00708                                         entry) == -1)
00709         {
00710           // Close the svc handler and reset <sh>.
00711           potential_handler->close (0);
00712 
00713           return -1;
00714         }
00715 
00716       // Everything succeeded as planned. Assign <sh> to
00717       // <potential_handler>.
00718       sh = potential_handler;
00719 
00720       // Set the recycler and the recycling act
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 /* ACE_CACHED_CONNECT_STRATEGY_T_CPP */

Generated on Thu Nov 9 09:41:47 2006 for ACE by doxygen 1.3.6