00001
00002
00003 #include "ace/INet/ConnectionCache.h"
00004
00005 #if !defined (__ACE_INLINE__)
00006 #include "ace/INet/ConnectionCache.inl"
00007 #endif
00008
00009 #include "ace/INet/INet_Log.h"
00010
00011 ACE_RCSID(NET_CLIENT,ACE_INet_ConnectionCache,"$Id: ConnectionCache.cpp 91118 2010-07-17 10:29:57Z mcorino $")
00012
00013 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00014
00015 namespace ACE
00016 {
00017 namespace INet
00018 {
00019
00020 ConnectionKey::ConnectionKey ()
00021 {}
00022
00023 ConnectionKey::~ConnectionKey ()
00024 {}
00025
00026 ConnectionCacheKey::ConnectionCacheKey ()
00027 : key_ (0),
00028 delete_key_ (false)
00029 {
00030 }
00031
00032 ConnectionCacheKey::ConnectionCacheKey (const ConnectionKey& key)
00033 : key_ (&const_cast<ConnectionKey&> (key)),
00034 delete_key_ (false)
00035 {
00036 }
00037
00038 ConnectionCacheKey::ConnectionCacheKey (const ConnectionCacheKey& cachekey)
00039 : key_ (0),
00040 delete_key_ (false)
00041 {
00042 *this = cachekey;
00043 }
00044
00045 ConnectionCacheKey& ConnectionCacheKey::operator =(const ConnectionCacheKey& cachekey)
00046 {
00047 if (this != &cachekey)
00048 {
00049 if (this->key_ != 0 && this->delete_key_)
00050 {
00051 delete this->key_;
00052 this->delete_key_ = false;
00053 }
00054
00055 this->key_ = cachekey.key_->duplicate ();
00056
00057 if (this->key_ == 0)
00058 {
00059 this->delete_key_ = false;
00060 }
00061 else
00062 {
00063 this->delete_key_ = true;
00064 }
00065 }
00066 return *this;
00067 }
00068
00069 u_long ConnectionCacheKey::hash (void) const
00070 {
00071 return this->key_ ? this->key ().hash () : 0;
00072 }
00073
00074 ConnectionHolder::~ConnectionHolder () {}
00075 ConnectionHolder::ConnectionHolder () {}
00076
00077 ConnectionFactory::~ConnectionFactory () {}
00078 ConnectionFactory::ConnectionFactory () {}
00079
00080 ConnectionCacheValue::ConnectionCacheValue ()
00081 : state_ (CST_INIT),
00082 connection_ (0)
00083 {
00084 }
00085
00086 ConnectionCacheValue::ConnectionCacheValue (connection_type* connection)
00087 : state_ (connection ? CST_IDLE : CST_INIT),
00088 connection_ (connection)
00089 {
00090 }
00091
00092 ConnectionCacheValue::ConnectionCacheValue (const ConnectionCacheValue& cacheval)
00093 {
00094 *this = cacheval;
00095 }
00096
00097 ConnectionCacheValue& ConnectionCacheValue::operator =(const ConnectionCacheValue& cacheval)
00098 {
00099 if (this != &cacheval)
00100 {
00101 this->state_ = cacheval.state ();
00102 this->connection_ = const_cast<connection_type*> (cacheval.connection ());
00103 }
00104 return *this;
00105 }
00106
00107 ConnectionCache::ConnectionCache(size_t size)
00108 : condition_ (lock_),
00109 cache_map_ (size)
00110 {
00111 }
00112
00113 ConnectionCache::~ConnectionCache ()
00114 {
00115 this->close_all_connections ();
00116 }
00117
00118 bool ConnectionCache::find_connection (const ConnectionKey& key,
00119 ConnectionCacheValue& cacheval)
00120 {
00121 if (this->cache_map_.find (ConnectionCacheKey (key),
00122 cacheval) == 0)
00123 {
00124 return true;
00125 }
00126 return false;
00127 }
00128
00129 bool ConnectionCache::set_connection (const ConnectionKey& key,
00130 const ConnectionCacheValue& cacheval)
00131 {
00132 return this->cache_map_.rebind (ConnectionCacheKey (key),
00133 cacheval) != -1;
00134 }
00135
00136 bool ConnectionCache::claim_existing_connection(const ConnectionKey& key,
00137 connection_type*& connection,
00138 ConnectionCacheValue::State& state)
00139 {
00140 INET_TRACE ("ConnectionCache::claim_existing_connection");
00141
00142 ConnectionCacheValue cacheval;
00143 if (this->find_connection (key, cacheval))
00144 {
00145 state = cacheval.state ();
00146 if (state == ConnectionCacheValue::CST_IDLE)
00147 {
00148 cacheval.state (ConnectionCacheValue::CST_BUSY);
00149 if (this->set_connection (key, cacheval))
00150 {
00151 connection = cacheval.connection ();
00152 return true;
00153 }
00154 else
00155 {
00156 INET_ERROR (1, (LM_ERROR, DLINFO ACE_TEXT ("ConnectionCache::claim_existing_connection - ")
00157 ACE_TEXT ("failed to claim connection entry")));
00158 }
00159 }
00160 }
00161 return false;
00162 }
00163
00164 bool ConnectionCache::claim_connection(const ConnectionKey& key,
00165 connection_type*& connection,
00166 const factory_type& connection_factory,
00167 bool wait)
00168 {
00169 INET_TRACE ("ConnectionCache::claim_connection");
00170
00171 while (1)
00172 {
00173 bool create_connection = false;
00174 ConnectionCacheValue::State state = ConnectionCacheValue::CST_NONE;
00175 do
00176 {
00177 ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX,
00178 guard_,
00179 this->lock_,
00180 false));
00181
00182 if (this->claim_existing_connection (key, connection, state))
00183 {
00184 INET_DEBUG (9, (LM_INFO, DLINFO ACE_TEXT ("%P|%t) ConnectionCache::claim_connection - ")
00185 ACE_TEXT ("successfully claimed existing connection\n")));
00186 return true;
00187 }
00188
00189 if ((state == ConnectionCacheValue::CST_BUSY ||
00190 state == ConnectionCacheValue::CST_INIT) && !wait)
00191 return false;
00192
00193 if (state == ConnectionCacheValue::CST_CLOSED ||
00194 state == ConnectionCacheValue::CST_NONE)
00195 {
00196 if (!this->set_connection (key, ConnectionCacheValue ()))
00197 {
00198 INET_ERROR (1, (LM_ERROR, DLINFO ACE_TEXT ("ConnectionCache::claim_connection - ")
00199 ACE_TEXT ("failed to initialize connection entry")));
00200 return false;
00201 }
00202
00203 create_connection = true;
00204 }
00205 else
00206 {
00207 INET_DEBUG (9, (LM_INFO, DLINFO ACE_TEXT ("ConnectionCache::claim_connection - ")
00208 ACE_TEXT ("waiting for connection to become available\n")));
00209
00210 if (this->condition_.wait () != 0)
00211 {
00212 INET_ERROR (1, (LM_ERROR, DLINFO ACE_TEXT ("(%P|%t) ConnectionCache::claim_connection - ")
00213 ACE_TEXT ("error waiting for connection condition (%p)\n")));
00214 return false;
00215 }
00216 INET_DEBUG (9, (LM_INFO, DLINFO ACE_TEXT ("ConnectionCache::claim_connection - ")
00217 ACE_TEXT ("awoken and retrying to claim connection\n")));
00218 }
00219 }
00220 while (0);
00221
00222 if (create_connection)
00223 {
00224 connection = connection_factory.create_connection (key);
00225 if (connection)
00226 {
00227 INET_DEBUG (9, (LM_INFO, DLINFO ACE_TEXT ("ConnectionCache::claim_connection - ")
00228 ACE_TEXT ("successfully created new connection\n")));
00229
00230 ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX,
00231 guard_,
00232 this->lock_,
00233 false));
00234
00235 ConnectionCacheValue cacheval (connection);
00236 cacheval.state (ConnectionCacheValue::CST_BUSY);
00237 return this->set_connection (key, cacheval);
00238 }
00239 else
00240 return false;
00241 }
00242 }
00243 }
00244
00245 bool ConnectionCache::release_connection(const ConnectionKey& key,
00246 connection_type* connection)
00247 {
00248 INET_TRACE ("ConnectionCache::release_connection");
00249
00250 INET_DEBUG (9, (LM_INFO, DLINFO ACE_TEXT ("ConnectionCache::release_connection - ")
00251 ACE_TEXT ("releasing connection\n")));
00252
00253 ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX,
00254 guard_,
00255 this->lock_,
00256 false));
00257
00258 ConnectionCacheValue cacheval;
00259 if (this->find_connection (key, cacheval) &&
00260 cacheval.connection () == connection &&
00261 cacheval.state () == ConnectionCacheValue::CST_BUSY)
00262 {
00263 cacheval.state (ConnectionCacheValue::CST_IDLE);
00264 if (this->set_connection (key, cacheval))
00265 {
00266
00267 this->condition_.broadcast ();
00268 return true;
00269 }
00270 else
00271 {
00272 INET_ERROR (1, (LM_ERROR, DLINFO ACE_TEXT ("ConnectionCache::release_connection - ")
00273 ACE_TEXT ("failed to release connection entry")));
00274 return false;
00275 }
00276 }
00277 else
00278 return false;
00279 }
00280
00281 bool ConnectionCache::close_connection(const ConnectionKey& key,
00282 connection_type* connection)
00283 {
00284 INET_TRACE ("ConnectionCache::close_connection");
00285
00286 INET_DEBUG (9, (LM_INFO, DLINFO ACE_TEXT ("ConnectionCache::close_connection - ")
00287 ACE_TEXT ("closing connection\n")));
00288
00289 ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX,
00290 guard_,
00291 this->lock_,
00292 false));
00293
00294 ConnectionCacheValue cacheval;
00295 if (this->find_connection (key, cacheval) &&
00296 cacheval.connection () == connection &&
00297 cacheval.state () == ConnectionCacheValue::CST_BUSY)
00298 {
00299 connection_type* conn = cacheval.connection ();
00300 cacheval.connection (0);
00301 cacheval.state (ConnectionCacheValue::CST_CLOSED);
00302 if (this->set_connection (key, cacheval))
00303 {
00304
00305 this->condition_.broadcast ();
00306 delete conn;
00307 return true;
00308 }
00309 else
00310 {
00311 INET_ERROR (1, (LM_ERROR, DLINFO ACE_TEXT ("ConnectionCache::close_connection - ")
00312 ACE_TEXT ("failed to close connection entry")));
00313 return false;
00314 }
00315 }
00316 else
00317 return false;
00318 }
00319
00320 bool ConnectionCache::has_connection(const ConnectionKey& key)
00321 {
00322 INET_TRACE ("ConnectionCache::has_connection");
00323
00324 ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX,
00325 guard_,
00326 this->lock_,
00327 false));
00328
00329 ConnectionCacheValue cacheval;
00330 return (this->find_connection (key, cacheval) &&
00331 cacheval.state () != ConnectionCacheValue::CST_CLOSED);
00332 }
00333
00334 void ConnectionCache::close_all_connections()
00335 {
00336 INET_TRACE ("ConnectionCache::close_all_connections");
00337
00338 ACE_MT (ACE_GUARD (ACE_SYNCH_MUTEX,
00339 guard_,
00340 this->lock_));
00341
00342 map_iter_type iter = this->cache_map_.end ();
00343 for (iter = this->cache_map_.begin ();
00344 iter != this->cache_map_.end ();
00345 ++iter)
00346 {
00347 if ((*iter).int_id_.state () == ConnectionCacheValue::CST_CLOSED)
00348 {
00349 connection_type* conn = (*iter).int_id_.connection ();
00350 (*iter).int_id_.connection (0);
00351 (*iter).int_id_.state (ConnectionCacheValue::CST_CLOSED);
00352 delete conn;
00353 }
00354 }
00355 this->cache_map_.unbind_all ();
00356 }
00357
00358 }
00359 }
00360
00361 ACE_END_VERSIONED_NAMESPACE_DECL