Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/socket/client_socket_pool_base.h" | 5 #include "net/socket/client_socket_pool_base.h" |
| 6 | 6 |
| 7 #include "base/compiler_specific.h" | 7 #include "base/compiler_specific.h" |
| 8 #include "base/format_macros.h" | 8 #include "base/format_macros.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/message_loop/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 158 : handle_(handle), | 158 : handle_(handle), |
| 159 callback_(callback), | 159 callback_(callback), |
| 160 priority_(priority), | 160 priority_(priority), |
| 161 ignore_limits_(ignore_limits), | 161 ignore_limits_(ignore_limits), |
| 162 flags_(flags), | 162 flags_(flags), |
| 163 net_log_(net_log) {} | 163 net_log_(net_log) {} |
| 164 | 164 |
| 165 ClientSocketPoolBaseHelper::Request::~Request() {} | 165 ClientSocketPoolBaseHelper::Request::~Request() {} |
| 166 | 166 |
| 167 ClientSocketPoolBaseHelper::ClientSocketPoolBaseHelper( | 167 ClientSocketPoolBaseHelper::ClientSocketPoolBaseHelper( |
| 168 HigherLayeredPool* pool, | |
| 168 int max_sockets, | 169 int max_sockets, |
| 169 int max_sockets_per_group, | 170 int max_sockets_per_group, |
| 170 base::TimeDelta unused_idle_socket_timeout, | 171 base::TimeDelta unused_idle_socket_timeout, |
| 171 base::TimeDelta used_idle_socket_timeout, | 172 base::TimeDelta used_idle_socket_timeout, |
| 172 ConnectJobFactory* connect_job_factory) | 173 ConnectJobFactory* connect_job_factory) |
| 173 : idle_socket_count_(0), | 174 : idle_socket_count_(0), |
| 174 connecting_socket_count_(0), | 175 connecting_socket_count_(0), |
| 175 handed_out_socket_count_(0), | 176 handed_out_socket_count_(0), |
| 176 max_sockets_(max_sockets), | 177 max_sockets_(max_sockets), |
| 177 max_sockets_per_group_(max_sockets_per_group), | 178 max_sockets_per_group_(max_sockets_per_group), |
| 178 use_cleanup_timer_(g_cleanup_timer_enabled), | 179 use_cleanup_timer_(g_cleanup_timer_enabled), |
| 179 unused_idle_socket_timeout_(unused_idle_socket_timeout), | 180 unused_idle_socket_timeout_(unused_idle_socket_timeout), |
| 180 used_idle_socket_timeout_(used_idle_socket_timeout), | 181 used_idle_socket_timeout_(used_idle_socket_timeout), |
| 181 connect_job_factory_(connect_job_factory), | 182 connect_job_factory_(connect_job_factory), |
| 182 connect_backup_jobs_enabled_(false), | 183 connect_backup_jobs_enabled_(false), |
| 183 pool_generation_number_(0), | 184 pool_generation_number_(0), |
| 185 pool_(pool), | |
| 184 weak_factory_(this) { | 186 weak_factory_(this) { |
| 185 DCHECK_LE(0, max_sockets_per_group); | 187 DCHECK_LE(0, max_sockets_per_group); |
| 186 DCHECK_LE(max_sockets_per_group, max_sockets); | 188 DCHECK_LE(max_sockets_per_group, max_sockets); |
| 187 | 189 |
| 188 NetworkChangeNotifier::AddIPAddressObserver(this); | 190 NetworkChangeNotifier::AddIPAddressObserver(this); |
| 189 } | 191 } |
| 190 | 192 |
| 191 ClientSocketPoolBaseHelper::~ClientSocketPoolBaseHelper() { | 193 ClientSocketPoolBaseHelper::~ClientSocketPoolBaseHelper() { |
| 192 // Clean up any idle sockets and pending connect jobs. Assert that we have no | 194 // Clean up any idle sockets and pending connect jobs. Assert that we have no |
| 193 // remaining active sockets or pending requests. They should have all been | 195 // remaining active sockets or pending requests. They should have all been |
| 194 // cleaned up prior to |this| being destroyed. | 196 // cleaned up prior to |this| being destroyed. |
| 195 FlushWithError(ERR_ABORTED); | 197 FlushWithError(ERR_ABORTED); |
| 196 DCHECK(group_map_.empty()); | 198 DCHECK(group_map_.empty()); |
| 197 DCHECK(pending_callback_map_.empty()); | 199 DCHECK(pending_callback_map_.empty()); |
| 198 DCHECK_EQ(0, connecting_socket_count_); | 200 DCHECK_EQ(0, connecting_socket_count_); |
| 199 CHECK(higher_layer_pools_.empty()); | 201 CHECK(higher_pools_.empty()); |
| 200 | 202 |
| 201 NetworkChangeNotifier::RemoveIPAddressObserver(this); | 203 NetworkChangeNotifier::RemoveIPAddressObserver(this); |
| 204 | |
| 205 // Remove from lower layer pools. | |
| 206 for (std::set<LowerLayeredPool*>::iterator it = lower_pools_.begin(); | |
| 207 it != lower_pools_.end(); | |
| 208 ++it) { | |
| 209 (*it)->RemoveHigherLayeredPool(pool_); | |
| 210 } | |
| 202 } | 211 } |
| 203 | 212 |
| 204 ClientSocketPoolBaseHelper::CallbackResultPair::CallbackResultPair() | 213 ClientSocketPoolBaseHelper::CallbackResultPair::CallbackResultPair() |
| 205 : result(OK) { | 214 : result(OK) { |
| 206 } | 215 } |
| 207 | 216 |
| 208 ClientSocketPoolBaseHelper::CallbackResultPair::CallbackResultPair( | 217 ClientSocketPoolBaseHelper::CallbackResultPair::CallbackResultPair( |
| 209 const CompletionCallback& callback_in, int result_in) | 218 const CompletionCallback& callback_in, int result_in) |
| 210 : callback(callback_in), | 219 : callback(callback_in), |
| 211 result(result_in) { | 220 result(result_in) { |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 231 ClientSocketPoolBaseHelper::RemoveRequestFromQueue( | 240 ClientSocketPoolBaseHelper::RemoveRequestFromQueue( |
| 232 const RequestQueue::iterator& it, Group* group) { | 241 const RequestQueue::iterator& it, Group* group) { |
| 233 const Request* req = *it; | 242 const Request* req = *it; |
| 234 group->mutable_pending_requests()->erase(it); | 243 group->mutable_pending_requests()->erase(it); |
| 235 // If there are no more requests, we kill the backup timer. | 244 // If there are no more requests, we kill the backup timer. |
| 236 if (group->pending_requests().empty()) | 245 if (group->pending_requests().empty()) |
| 237 group->CleanupBackupJob(); | 246 group->CleanupBackupJob(); |
| 238 return req; | 247 return req; |
| 239 } | 248 } |
| 240 | 249 |
| 241 void ClientSocketPoolBaseHelper::AddLayeredPool(LayeredPool* pool) { | 250 bool ClientSocketPoolBaseHelper::IsStalled() const { |
| 242 CHECK(pool); | 251 // If a lower layer pool is stalled, consider |this| stalled as well. |
| 243 CHECK(!ContainsKey(higher_layer_pools_, pool)); | 252 for (std::set<LowerLayeredPool*>::const_iterator it = lower_pools_.begin(); |
| 244 higher_layer_pools_.insert(pool); | 253 it != lower_pools_.end(); |
| 254 ++it) { | |
| 255 if ((*it)->IsStalled()) | |
| 256 return true; | |
| 257 } | |
| 258 | |
| 259 // If we are not using |max_sockets_|, then clearly we are not stalled. | |
|
akalin
2013/08/22 19:23:25
"not using |max_sockets_|" can be interpreted as "
mmenke
2013/08/22 19:53:05
Done. I also removed use of "we" (This was actual
| |
| 260 if ((handed_out_socket_count_ + connecting_socket_count_) < max_sockets_) | |
| 261 return false; | |
| 262 // So in order to be stalled we need to be using |max_sockets_| AND | |
|
akalin
2013/08/22 19:23:25
same thing here? (although I realize it's kinda aw
mmenke
2013/08/22 19:53:05
Done (-> "using at least |max_sockets_|"). Also g
| |
| 263 // we need to have a request that is actually stalled on the global | |
| 264 // socket limit. To find such a request, we look for a group that | |
| 265 // a has more requests that jobs AND where the number of jobs is less | |
| 266 // than |max_sockets_per_group_|. (If the number of jobs is equal to | |
| 267 // |max_sockets_per_group_|, then the request is stalled on the group, | |
| 268 // which does not count.) | |
| 269 for (GroupMap::const_iterator it = group_map_.begin(); | |
| 270 it != group_map_.end(); ++it) { | |
| 271 if (it->second->IsStalledOnPoolMaxSockets(max_sockets_per_group_)) | |
| 272 return true; | |
| 273 } | |
| 274 return false; | |
| 245 } | 275 } |
| 246 | 276 |
| 247 void ClientSocketPoolBaseHelper::RemoveLayeredPool(LayeredPool* pool) { | 277 void ClientSocketPoolBaseHelper::AddLowerLayeredPool( |
| 248 CHECK(pool); | 278 LowerLayeredPool* lower_pool) { |
| 249 CHECK(ContainsKey(higher_layer_pools_, pool)); | 279 DCHECK(pool_); |
| 250 higher_layer_pools_.erase(pool); | 280 CHECK(!ContainsKey(lower_pools_, lower_pool)); |
| 281 lower_pools_.insert(lower_pool); | |
| 282 lower_pool->AddHigherLayeredPool(pool_); | |
| 283 } | |
| 284 | |
| 285 void ClientSocketPoolBaseHelper::AddHigherLayeredPool( | |
| 286 HigherLayeredPool* higher_pool) { | |
| 287 CHECK(higher_pool); | |
| 288 CHECK(!ContainsKey(higher_pools_, higher_pool)); | |
| 289 higher_pools_.insert(higher_pool); | |
| 290 } | |
| 291 | |
| 292 void ClientSocketPoolBaseHelper::RemoveHigherLayeredPool( | |
| 293 HigherLayeredPool* higher_pool) { | |
| 294 CHECK(higher_pool); | |
| 295 CHECK(ContainsKey(higher_pools_, higher_pool)); | |
| 296 higher_pools_.erase(higher_pool); | |
| 251 } | 297 } |
| 252 | 298 |
| 253 int ClientSocketPoolBaseHelper::RequestSocket( | 299 int ClientSocketPoolBaseHelper::RequestSocket( |
| 254 const std::string& group_name, | 300 const std::string& group_name, |
| 255 const Request* request) { | 301 const Request* request) { |
| 256 CHECK(!request->callback().is_null()); | 302 CHECK(!request->callback().is_null()); |
| 257 CHECK(request->handle()); | 303 CHECK(request->handle()); |
| 258 | 304 |
| 259 // Cleanup any timed-out idle sockets if no timer is used. | 305 // Cleanup any timed-out idle sockets if no timer is used. |
| 260 if (!use_cleanup_timer_) | 306 if (!use_cleanup_timer_) |
| (...skipping 522 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 783 socket.reset(); | 829 socket.reset(); |
| 784 } | 830 } |
| 785 | 831 |
| 786 CheckForStalledSocketGroups(); | 832 CheckForStalledSocketGroups(); |
| 787 } | 833 } |
| 788 | 834 |
| 789 void ClientSocketPoolBaseHelper::CheckForStalledSocketGroups() { | 835 void ClientSocketPoolBaseHelper::CheckForStalledSocketGroups() { |
| 790 // If we have idle sockets, see if we can give one to the top-stalled group. | 836 // If we have idle sockets, see if we can give one to the top-stalled group. |
| 791 std::string top_group_name; | 837 std::string top_group_name; |
| 792 Group* top_group = NULL; | 838 Group* top_group = NULL; |
| 793 if (!FindTopStalledGroup(&top_group, &top_group_name)) | 839 if (!FindTopStalledGroup(&top_group, &top_group_name)) { |
| 840 // There may still be a stalled group in a lower level pool. | |
| 841 for (std::set<LowerLayeredPool*>::iterator it = lower_pools_.begin(); | |
| 842 it != lower_pools_.end(); | |
| 843 ++it) { | |
| 844 if ((*it)->IsStalled()) { | |
| 845 CloseOneIdleSocket(); | |
| 846 break; | |
| 847 } | |
| 848 } | |
| 794 return; | 849 return; |
| 850 } | |
| 795 | 851 |
| 796 if (ReachedMaxSocketsLimit()) { | 852 if (ReachedMaxSocketsLimit()) { |
| 797 if (idle_socket_count() > 0) { | 853 if (idle_socket_count() > 0) { |
| 798 CloseOneIdleSocket(); | 854 CloseOneIdleSocket(); |
| 799 } else { | 855 } else { |
| 800 // We can't activate more sockets since we're already at our global | 856 // We can't activate more sockets since we're already at our global |
| 801 // limit. | 857 // limit. |
| 802 return; | 858 return; |
| 803 } | 859 } |
| 804 } | 860 } |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 917 FlushWithError(ERR_NETWORK_CHANGED); | 973 FlushWithError(ERR_NETWORK_CHANGED); |
| 918 } | 974 } |
| 919 | 975 |
| 920 void ClientSocketPoolBaseHelper::FlushWithError(int error) { | 976 void ClientSocketPoolBaseHelper::FlushWithError(int error) { |
| 921 pool_generation_number_++; | 977 pool_generation_number_++; |
| 922 CancelAllConnectJobs(); | 978 CancelAllConnectJobs(); |
| 923 CloseIdleSockets(); | 979 CloseIdleSockets(); |
| 924 CancelAllRequestsWithError(error); | 980 CancelAllRequestsWithError(error); |
| 925 } | 981 } |
| 926 | 982 |
| 927 bool ClientSocketPoolBaseHelper::IsStalled() const { | |
| 928 // If we are not using |max_sockets_|, then clearly we are not stalled | |
| 929 if ((handed_out_socket_count_ + connecting_socket_count_) < max_sockets_) | |
| 930 return false; | |
| 931 // So in order to be stalled we need to be using |max_sockets_| AND | |
| 932 // we need to have a request that is actually stalled on the global | |
| 933 // socket limit. To find such a request, we look for a group that | |
| 934 // a has more requests that jobs AND where the number of jobs is less | |
| 935 // than |max_sockets_per_group_|. (If the number of jobs is equal to | |
| 936 // |max_sockets_per_group_|, then the request is stalled on the group, | |
| 937 // which does not count.) | |
| 938 for (GroupMap::const_iterator it = group_map_.begin(); | |
| 939 it != group_map_.end(); ++it) { | |
| 940 if (it->second->IsStalledOnPoolMaxSockets(max_sockets_per_group_)) | |
| 941 return true; | |
| 942 } | |
| 943 return false; | |
| 944 } | |
| 945 | |
| 946 void ClientSocketPoolBaseHelper::RemoveConnectJob(ConnectJob* job, | 983 void ClientSocketPoolBaseHelper::RemoveConnectJob(ConnectJob* job, |
| 947 Group* group) { | 984 Group* group) { |
| 948 CHECK_GT(connecting_socket_count_, 0); | 985 CHECK_GT(connecting_socket_count_, 0); |
| 949 connecting_socket_count_--; | 986 connecting_socket_count_--; |
| 950 | 987 |
| 951 DCHECK(group); | 988 DCHECK(group); |
| 952 group->RemoveJob(job); | 989 group->RemoveJob(job); |
| 953 | 990 |
| 954 // If we've got no more jobs for this group, then we no longer need a | 991 // If we've got no more jobs for this group, then we no longer need a |
| 955 // backup job either. | 992 // backup job either. |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1101 if (group->IsEmpty()) | 1138 if (group->IsEmpty()) |
| 1102 RemoveGroup(i); | 1139 RemoveGroup(i); |
| 1103 | 1140 |
| 1104 return true; | 1141 return true; |
| 1105 } | 1142 } |
| 1106 } | 1143 } |
| 1107 | 1144 |
| 1108 return false; | 1145 return false; |
| 1109 } | 1146 } |
| 1110 | 1147 |
| 1111 bool ClientSocketPoolBaseHelper::CloseOneIdleConnectionInLayeredPool() { | 1148 bool ClientSocketPoolBaseHelper::CloseOneIdleConnectionInHigherLayeredPool() { |
| 1112 // This pool doesn't have any idle sockets. It's possible that a pool at a | 1149 // This pool doesn't have any idle sockets. It's possible that a pool at a |
| 1113 // higher layer is holding one of this sockets active, but it's actually idle. | 1150 // higher layer is holding one of this sockets active, but it's actually idle. |
| 1114 // Query the higher layers. | 1151 // Query the higher layers. |
| 1115 for (std::set<LayeredPool*>::const_iterator it = higher_layer_pools_.begin(); | 1152 for (std::set<HigherLayeredPool*>::const_iterator it = higher_pools_.begin(); |
| 1116 it != higher_layer_pools_.end(); ++it) { | 1153 it != higher_pools_.end(); ++it) { |
| 1117 if ((*it)->CloseOneIdleConnection()) | 1154 if ((*it)->CloseOneIdleConnection()) |
| 1118 return true; | 1155 return true; |
| 1119 } | 1156 } |
| 1120 return false; | 1157 return false; |
| 1121 } | 1158 } |
| 1122 | 1159 |
| 1123 void ClientSocketPoolBaseHelper::InvokeUserCallbackLater( | 1160 void ClientSocketPoolBaseHelper::InvokeUserCallbackLater( |
| 1124 ClientSocketHandle* handle, const CompletionCallback& callback, int rv) { | 1161 ClientSocketHandle* handle, const CompletionCallback& callback, int rv) { |
| 1125 CHECK(!ContainsKey(pending_callback_map_, handle)); | 1162 CHECK(!ContainsKey(pending_callback_map_, handle)); |
| 1126 pending_callback_map_[handle] = CallbackResultPair(callback, rv); | 1163 pending_callback_map_[handle] = CallbackResultPair(callback, rv); |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 1142 CompletionCallback callback = it->second.callback; | 1179 CompletionCallback callback = it->second.callback; |
| 1143 int result = it->second.result; | 1180 int result = it->second.result; |
| 1144 pending_callback_map_.erase(it); | 1181 pending_callback_map_.erase(it); |
| 1145 callback.Run(result); | 1182 callback.Run(result); |
| 1146 } | 1183 } |
| 1147 | 1184 |
| 1148 void ClientSocketPoolBaseHelper::TryToCloseSocketsInLayeredPools() { | 1185 void ClientSocketPoolBaseHelper::TryToCloseSocketsInLayeredPools() { |
| 1149 while (IsStalled()) { | 1186 while (IsStalled()) { |
| 1150 // Closing a socket will result in calling back into |this| to use the freed | 1187 // Closing a socket will result in calling back into |this| to use the freed |
| 1151 // socket slot, so nothing else is needed. | 1188 // socket slot, so nothing else is needed. |
| 1152 if (!CloseOneIdleConnectionInLayeredPool()) | 1189 if (!CloseOneIdleConnectionInHigherLayeredPool()) |
| 1153 return; | 1190 return; |
| 1154 } | 1191 } |
| 1155 } | 1192 } |
| 1156 | 1193 |
| 1157 ClientSocketPoolBaseHelper::Group::Group() | 1194 ClientSocketPoolBaseHelper::Group::Group() |
| 1158 : unassigned_job_count_(0), | 1195 : unassigned_job_count_(0), |
| 1159 active_socket_count_(0), | 1196 active_socket_count_(0), |
| 1160 weak_factory_(this) {} | 1197 weak_factory_(this) {} |
| 1161 | 1198 |
| 1162 ClientSocketPoolBaseHelper::Group::~Group() { | 1199 ClientSocketPoolBaseHelper::Group::~Group() { |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1257 STLDeleteElements(&jobs_); | 1294 STLDeleteElements(&jobs_); |
| 1258 unassigned_job_count_ = 0; | 1295 unassigned_job_count_ = 0; |
| 1259 | 1296 |
| 1260 // Cancel pending backup job. | 1297 // Cancel pending backup job. |
| 1261 weak_factory_.InvalidateWeakPtrs(); | 1298 weak_factory_.InvalidateWeakPtrs(); |
| 1262 } | 1299 } |
| 1263 | 1300 |
| 1264 } // namespace internal | 1301 } // namespace internal |
| 1265 | 1302 |
| 1266 } // namespace net | 1303 } // namespace net |
| OLD | NEW |