Cached_Connect_Strategy_T.cpp

Go to the documentation of this file.
00001 //$Id: Cached_Connect_Strategy_T.cpp 80826 2008-03-04 14:51:23Z wotte $
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_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   // Get the recycling act for the svc_handler
00070   CONNECTION_CACHE_ENTRY *possible_entry =
00071     (CONNECTION_CACHE_ENTRY *) sh->recycling_act ();
00072 
00073   // Check to see if the hint svc_handler has been closed down
00074   if (possible_entry->ext_id_.recycle_state () == ACE_RECYCLABLE_CLOSED)
00075     {
00076       // If close, decrement refcount
00077       if (possible_entry->ext_id_.decrement () == 0)
00078         {
00079           // If refcount goes to zero, close down the svc_handler
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       // Hint not successful
00086       found = 0;
00087 
00088       // Reset hint
00089       sh = 0;
00090     }
00091 
00092   // If hint is not closed, see if it is connected to the correct
00093   // address and is recyclable
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       // Hint successful
00099       found = 1;
00100 
00101       // Tell the <svc_handler> that it should prepare itself for
00102       // being recycled.
00103       this->prepare_for_recycling (sh);
00104 
00105       //
00106       // Update the caching attributes directly since we don't do a
00107       // find() on the cache map.
00108       //
00109 
00110       // Indicates successful find.
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       // This hint will not be used.
00122       possible_entry->ext_id_.decrement ();
00123 
00124       // Hint not successful
00125       found = 0;
00126 
00127       // If <sh> is not connected to the correct address or is busy,
00128       // we will not use it.
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   // Try to find the address in the cache.  Only if we don't find it
00153   // do we create a new <SVC_HANDLER> and connect it with the server.
00154   while (this->find (search_addr, entry) != -1)
00155   {
00156     // We found a cached svc_handler.
00157     // Get the cached <svc_handler>
00158     sh = entry->int_id_.first ();
00159 
00160     // Is the connection clean?
00161     int state_result =
00162       ACE::handle_ready (sh->peer ().get_handle (),
00163                          &ACE_Time_Value::zero,
00164                          1, // read ready
00165                          0, // write ready
00166                          1);// exception ready
00167 
00168     if (state_result == 1)
00169     {
00170 
00171       if (sh->close () == -1)
00172         return -1;
00173 
00174       sh = 0;
00175 
00176       // Cycle it once again..
00177     }
00178     else if ((state_result == -1) && (errno == ETIME))
00179     {
00180       // Found!!!
00181       // Set the flag
00182       found = 1;
00183 
00184       // Tell the <svc_handler> that it should prepare itself for
00185       // being recycled.
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   // Not found...
00198 
00199   // Set the flag
00200   found = 0;
00201 
00202   // We need to use a temporary variable here since we are not
00203   // allowed to change <sh> because other threads may use this
00204   // when we let go of the lock during the OS level connect.
00205   //
00206   // Note that making a new svc_handler, connecting remotely,
00207   // binding to the map, and assigning of the hint and recycler
00208   // should be atomic to the outside world.
00209   SVC_HANDLER *potential_handler = 0;
00210 
00211   // Create a new svc_handler
00212   if (this->make_svc_handler (potential_handler) == -1)
00213     return -1;
00214 
00215   // Connect using the svc_handler.
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       // Close the svc handler.
00225       potential_handler->close (0);
00226 
00227       return -1;
00228     }
00229     else
00230     {
00231       // Insert the new SVC_HANDLER instance into the cache.
00232       if (this->connection_cache_.bind (search_addr,
00233                                         potential_handler,
00234                                         entry) == -1)
00235         {
00236           // Close the svc handler and reset <sh>.
00237           potential_handler->close (0);
00238 
00239           return -1;
00240         }
00241 
00242       // Everything succeeded as planned. Assign <sh> to
00243       // <potential_handler>.
00244       sh = potential_handler;
00245 
00246       // Set the recycler and the recycling act
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   // Actively establish the connection.  This is a timed blocking
00264   // connect.
00265   if (this->new_connection (sh,
00266                             remote_addr,
00267                             timeout,
00268                             local_addr,
00269                             reuse_addr,
00270                             flags,
00271                             perms) == -1)
00272     {
00273       // If connect() failed because of timeouts, we have to reject
00274       // the connection entirely. This is necessary since currently
00275       // there is no way for the non-blocking connects to complete and
00276       // for the <Connector> to notify the cache of the completion of
00277       // connect().
00278 
00279       if (errno == EWOULDBLOCK || errno == ETIMEDOUT)
00280         errno = ENOTSUP;
00281       else if (ACE::out_of_handles (errno) || errno == EADDRINUSE)
00282         {
00283           // If the connect failed due to the process running out of
00284           // file descriptors then, auto_purging of some connections
00285           // are done from the CONNECTION_CACHE. This frees the
00286           // descriptors which get used in the connect process and
00287           // hence the same method is called again!
00288           if (this->purge_connections () == -1)
00289             return -1;
00290 
00291           // Try connecting again.
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   // Check if the user passed a hint svc_handler
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   // If not found
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       // Increment the refcount
00362       entry->ext_id_.increment ();
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   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   // The wonders and perils of ACT
00377   CONNECTION_CACHE_ENTRY *entry = (CONNECTION_CACHE_ENTRY *) recycling_act;
00378 
00379   // Mark the <svc_handler> in the cache as not being <in_use>.
00380   // Therefore recyclable is IDLE.
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   // The wonders and perils of ACT
00391   CONNECTION_CACHE_ENTRY *entry = (CONNECTION_CACHE_ENTRY *) recycling_act;
00392 
00393   // Mark the <svc_handler> in the cache as not being <in_use>.
00394   // Therefore recyclable is IDLE.
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   // The wonders and perils of ACT
00404   CONNECTION_CACHE_ENTRY *entry = (CONNECTION_CACHE_ENTRY *) recycling_act;
00405 
00406   // Mark the <svc_handler> in the cache as not being <in_use>.
00407   // Therefore recyclable is IDLE.
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   // The wonders and perils of ACT
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   // The wonders and perils of ACT
00425   CONNECTION_CACHE_ENTRY *entry = (CONNECTION_CACHE_ENTRY *) recycling_act;
00426 
00427   // Mark the <svc_handler> in the cache as CLOSED.
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   // Reset the <*act_holder> in the confines and protection of the
00438   // lock.
00439   if (act_holder)
00440     *act_holder = 0;
00441 
00442   // The wonders and perils of ACT
00443   CONNECTION_CACHE_ENTRY *entry = (CONNECTION_CACHE_ENTRY *) recycling_act;
00444 
00445   // Decrement the refcount on the <svc_handler>.
00446   int refcount = entry->ext_id_.decrement ();
00447 
00448   // If the svc_handler state is closed and the refcount == 0, call
00449   // close() on svc_handler.
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       // Update the caching attributes directly since we don't do a
00508       // find() on the cache map.
00509       //
00510 
00511       // Indicates successful find.
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   // Excluded other threads from changing the cache while we cleanup
00530   ACE_GUARD (MUTEX, ace_mon, *this->lock_);
00531 
00532   // Close down all cached service handlers.
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           // 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           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_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   // 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 Tue Feb 2 17:18:38 2010 for ACE by  doxygen 1.4.7