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.h" | 10 #include "base/message_loop.h" |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 154 : handle_(handle), | 154 : handle_(handle), |
| 155 callback_(callback), | 155 callback_(callback), |
| 156 priority_(priority), | 156 priority_(priority), |
| 157 ignore_limits_(ignore_limits), | 157 ignore_limits_(ignore_limits), |
| 158 flags_(flags), | 158 flags_(flags), |
| 159 net_log_(net_log) {} | 159 net_log_(net_log) {} |
| 160 | 160 |
| 161 ClientSocketPoolBaseHelper::Request::~Request() {} | 161 ClientSocketPoolBaseHelper::Request::~Request() {} |
| 162 | 162 |
| 163 ClientSocketPoolBaseHelper::ClientSocketPoolBaseHelper( | 163 ClientSocketPoolBaseHelper::ClientSocketPoolBaseHelper( |
| 164 HigherLayeredPool* pool, | |
| 164 int max_sockets, | 165 int max_sockets, |
| 165 int max_sockets_per_group, | 166 int max_sockets_per_group, |
| 166 base::TimeDelta unused_idle_socket_timeout, | 167 base::TimeDelta unused_idle_socket_timeout, |
| 167 base::TimeDelta used_idle_socket_timeout, | 168 base::TimeDelta used_idle_socket_timeout, |
| 168 ConnectJobFactory* connect_job_factory) | 169 ConnectJobFactory* connect_job_factory) |
| 169 : idle_socket_count_(0), | 170 : idle_socket_count_(0), |
| 170 connecting_socket_count_(0), | 171 connecting_socket_count_(0), |
| 171 handed_out_socket_count_(0), | 172 handed_out_socket_count_(0), |
| 172 max_sockets_(max_sockets), | 173 max_sockets_(max_sockets), |
| 173 max_sockets_per_group_(max_sockets_per_group), | 174 max_sockets_per_group_(max_sockets_per_group), |
| 174 use_cleanup_timer_(g_cleanup_timer_enabled), | 175 use_cleanup_timer_(g_cleanup_timer_enabled), |
| 175 unused_idle_socket_timeout_(unused_idle_socket_timeout), | 176 unused_idle_socket_timeout_(unused_idle_socket_timeout), |
| 176 used_idle_socket_timeout_(used_idle_socket_timeout), | 177 used_idle_socket_timeout_(used_idle_socket_timeout), |
| 177 connect_job_factory_(connect_job_factory), | 178 connect_job_factory_(connect_job_factory), |
| 178 connect_backup_jobs_enabled_(false), | 179 connect_backup_jobs_enabled_(false), |
| 179 pool_generation_number_(0), | 180 pool_generation_number_(0), |
| 181 pool_(pool), | |
| 180 weak_factory_(this) { | 182 weak_factory_(this) { |
| 181 DCHECK_LE(0, max_sockets_per_group); | 183 DCHECK_LE(0, max_sockets_per_group); |
| 182 DCHECK_LE(max_sockets_per_group, max_sockets); | 184 DCHECK_LE(max_sockets_per_group, max_sockets); |
| 183 | 185 |
| 184 NetworkChangeNotifier::AddIPAddressObserver(this); | 186 NetworkChangeNotifier::AddIPAddressObserver(this); |
| 185 } | 187 } |
| 186 | 188 |
| 187 ClientSocketPoolBaseHelper::~ClientSocketPoolBaseHelper() { | 189 ClientSocketPoolBaseHelper::~ClientSocketPoolBaseHelper() { |
| 188 // Clean up any idle sockets and pending connect jobs. Assert that we have no | 190 // Clean up any idle sockets and pending connect jobs. Assert that we have no |
| 189 // remaining active sockets or pending requests. They should have all been | 191 // remaining active sockets or pending requests. They should have all been |
| 190 // cleaned up prior to |this| being destroyed. | 192 // cleaned up prior to |this| being destroyed. |
| 191 FlushWithError(ERR_ABORTED); | 193 FlushWithError(ERR_ABORTED); |
| 192 DCHECK(group_map_.empty()); | 194 DCHECK(group_map_.empty()); |
| 193 DCHECK(pending_callback_map_.empty()); | 195 DCHECK(pending_callback_map_.empty()); |
| 194 DCHECK_EQ(0, connecting_socket_count_); | 196 DCHECK_EQ(0, connecting_socket_count_); |
| 195 CHECK(higher_layer_pools_.empty()); | 197 CHECK(higher_pools_.empty()); |
| 196 | 198 |
| 197 NetworkChangeNotifier::RemoveIPAddressObserver(this); | 199 NetworkChangeNotifier::RemoveIPAddressObserver(this); |
| 200 | |
| 201 // Remove from lower layer pools. | |
| 202 for (std::set<LowerLayeredPool*>::iterator it = lower_pools_.begin(); | |
| 203 it != lower_pools_.end(); | |
| 204 ++it) { | |
| 205 (*it)->RemoveHigherLayeredPool(pool_); | |
| 206 } | |
| 198 } | 207 } |
| 199 | 208 |
| 200 ClientSocketPoolBaseHelper::CallbackResultPair::CallbackResultPair() | 209 ClientSocketPoolBaseHelper::CallbackResultPair::CallbackResultPair() |
| 201 : result(OK) { | 210 : result(OK) { |
| 202 } | 211 } |
| 203 | 212 |
| 204 ClientSocketPoolBaseHelper::CallbackResultPair::CallbackResultPair( | 213 ClientSocketPoolBaseHelper::CallbackResultPair::CallbackResultPair( |
| 205 const CompletionCallback& callback_in, int result_in) | 214 const CompletionCallback& callback_in, int result_in) |
| 206 : callback(callback_in), | 215 : callback(callback_in), |
| 207 result(result_in) { | 216 result(result_in) { |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 227 ClientSocketPoolBaseHelper::RemoveRequestFromQueue( | 236 ClientSocketPoolBaseHelper::RemoveRequestFromQueue( |
| 228 const RequestQueue::iterator& it, Group* group) { | 237 const RequestQueue::iterator& it, Group* group) { |
| 229 const Request* req = *it; | 238 const Request* req = *it; |
| 230 group->mutable_pending_requests()->erase(it); | 239 group->mutable_pending_requests()->erase(it); |
| 231 // If there are no more requests, we kill the backup timer. | 240 // If there are no more requests, we kill the backup timer. |
| 232 if (group->pending_requests().empty()) | 241 if (group->pending_requests().empty()) |
| 233 group->CleanupBackupJob(); | 242 group->CleanupBackupJob(); |
| 234 return req; | 243 return req; |
| 235 } | 244 } |
| 236 | 245 |
| 237 void ClientSocketPoolBaseHelper::AddLayeredPool(LayeredPool* pool) { | 246 bool ClientSocketPoolBaseHelper::IsStalled() const { |
| 238 CHECK(pool); | 247 // If a lower layer pool is stalled, consider |this| stalled as well. |
|
Ryan Hamilton
2013/07/21 14:53:54
This seems like mostly a good idea, but how does i
mmenke
2013/07/22 20:13:33
SpdySessions can never be stalled. They aren't co
Ryan Hamilton
2013/07/22 20:22:46
Works for me. FWIW, there is a streams/session li
mmenke
2013/07/24 19:05:23
Yea, I don't think so - that would need to be deal
| |
| 239 CHECK(!ContainsKey(higher_layer_pools_, pool)); | 248 for (std::set<LowerLayeredPool*>::const_iterator it = lower_pools_.begin(); |
| 240 higher_layer_pools_.insert(pool); | 249 it != lower_pools_.end(); |
| 250 ++it) { | |
| 251 if ((*it)->IsStalled()) | |
| 252 return true; | |
| 253 } | |
| 254 | |
| 255 // If we are not using |max_sockets_|, then clearly we are not stalled | |
| 256 if ((handed_out_socket_count_ + connecting_socket_count_) < max_sockets_) | |
| 257 return false; | |
| 258 // So in order to be stalled we need to be using |max_sockets_| AND | |
| 259 // we need to have a request that is actually stalled on the global | |
| 260 // socket limit. To find such a request, we look for a group that | |
| 261 // a has more requests that jobs AND where the number of jobs is less | |
| 262 // than |max_sockets_per_group_|. (If the number of jobs is equal to | |
| 263 // |max_sockets_per_group_|, then the request is stalled on the group, | |
| 264 // which does not count.) | |
| 265 for (GroupMap::const_iterator it = group_map_.begin(); | |
| 266 it != group_map_.end(); ++it) { | |
| 267 if (it->second->IsStalledOnPoolMaxSockets(max_sockets_per_group_)) | |
| 268 return true; | |
| 269 } | |
| 270 return false; | |
| 241 } | 271 } |
| 242 | 272 |
| 243 void ClientSocketPoolBaseHelper::RemoveLayeredPool(LayeredPool* pool) { | 273 void ClientSocketPoolBaseHelper::AddLowerLayeredPool( |
| 244 CHECK(pool); | 274 LowerLayeredPool* lower_pool) { |
| 245 CHECK(ContainsKey(higher_layer_pools_, pool)); | 275 DCHECK(pool_); |
| 246 higher_layer_pools_.erase(pool); | 276 CHECK(!ContainsKey(lower_pools_, lower_pool)); |
| 277 lower_pools_.insert(lower_pool); | |
| 278 lower_pool->AddHigherLayeredPool(pool_); | |
| 279 } | |
| 280 | |
| 281 void ClientSocketPoolBaseHelper::AddHigherLayeredPool( | |
| 282 HigherLayeredPool* higher_pool) { | |
| 283 CHECK(higher_pool); | |
| 284 CHECK(!ContainsKey(higher_pools_, higher_pool)); | |
| 285 higher_pools_.insert(higher_pool); | |
| 286 } | |
| 287 | |
| 288 void ClientSocketPoolBaseHelper::RemoveHigherLayeredPool( | |
| 289 HigherLayeredPool* higher_pool) { | |
| 290 CHECK(higher_pool); | |
| 291 CHECK(ContainsKey(higher_pools_, higher_pool)); | |
| 292 higher_pools_.erase(higher_pool); | |
| 247 } | 293 } |
| 248 | 294 |
| 249 int ClientSocketPoolBaseHelper::RequestSocket( | 295 int ClientSocketPoolBaseHelper::RequestSocket( |
| 250 const std::string& group_name, | 296 const std::string& group_name, |
| 251 const Request* request) { | 297 const Request* request) { |
| 252 CHECK(!request->callback().is_null()); | 298 CHECK(!request->callback().is_null()); |
| 253 CHECK(request->handle()); | 299 CHECK(request->handle()); |
| 254 | 300 |
| 255 // Cleanup any timed-out idle sockets if no timer is used. | 301 // Cleanup any timed-out idle sockets if no timer is used. |
| 256 if (!use_cleanup_timer_) | 302 if (!use_cleanup_timer_) |
| (...skipping 520 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 777 delete socket; | 823 delete socket; |
| 778 } | 824 } |
| 779 | 825 |
| 780 CheckForStalledSocketGroups(); | 826 CheckForStalledSocketGroups(); |
| 781 } | 827 } |
| 782 | 828 |
| 783 void ClientSocketPoolBaseHelper::CheckForStalledSocketGroups() { | 829 void ClientSocketPoolBaseHelper::CheckForStalledSocketGroups() { |
| 784 // If we have idle sockets, see if we can give one to the top-stalled group. | 830 // If we have idle sockets, see if we can give one to the top-stalled group. |
| 785 std::string top_group_name; | 831 std::string top_group_name; |
| 786 Group* top_group = NULL; | 832 Group* top_group = NULL; |
| 787 if (!FindTopStalledGroup(&top_group, &top_group_name)) | 833 if (!FindTopStalledGroup(&top_group, &top_group_name)) { |
| 834 // There may still be a stalled group in a lower level pool. | |
| 835 for (std::set<LowerLayeredPool*>::iterator it = lower_pools_.begin(); | |
| 836 it != lower_pools_.end(); | |
| 837 ++it) { | |
| 838 if ((*it)->IsStalled()) { | |
| 839 CloseOneIdleSocket(); | |
| 840 break; | |
| 841 } | |
| 842 } | |
| 788 return; | 843 return; |
| 844 } | |
| 789 | 845 |
| 790 if (ReachedMaxSocketsLimit()) { | 846 if (ReachedMaxSocketsLimit()) { |
| 791 if (idle_socket_count() > 0) { | 847 if (idle_socket_count() > 0) { |
| 792 CloseOneIdleSocket(); | 848 CloseOneIdleSocket(); |
| 793 } else { | 849 } else { |
| 794 // We can't activate more sockets since we're already at our global | 850 // We can't activate more sockets since we're already at our global |
| 795 // limit. | 851 // limit. |
| 796 return; | 852 return; |
| 797 } | 853 } |
| 798 } | 854 } |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 908 FlushWithError(ERR_NETWORK_CHANGED); | 964 FlushWithError(ERR_NETWORK_CHANGED); |
| 909 } | 965 } |
| 910 | 966 |
| 911 void ClientSocketPoolBaseHelper::FlushWithError(int error) { | 967 void ClientSocketPoolBaseHelper::FlushWithError(int error) { |
| 912 pool_generation_number_++; | 968 pool_generation_number_++; |
| 913 CancelAllConnectJobs(); | 969 CancelAllConnectJobs(); |
| 914 CloseIdleSockets(); | 970 CloseIdleSockets(); |
| 915 CancelAllRequestsWithError(error); | 971 CancelAllRequestsWithError(error); |
| 916 } | 972 } |
| 917 | 973 |
| 918 bool ClientSocketPoolBaseHelper::IsStalled() const { | |
| 919 // If we are not using |max_sockets_|, then clearly we are not stalled | |
| 920 if ((handed_out_socket_count_ + connecting_socket_count_) < max_sockets_) | |
| 921 return false; | |
| 922 // So in order to be stalled we need to be using |max_sockets_| AND | |
| 923 // we need to have a request that is actually stalled on the global | |
| 924 // socket limit. To find such a request, we look for a group that | |
| 925 // a has more requests that jobs AND where the number of jobs is less | |
| 926 // than |max_sockets_per_group_|. (If the number of jobs is equal to | |
| 927 // |max_sockets_per_group_|, then the request is stalled on the group, | |
| 928 // which does not count.) | |
| 929 for (GroupMap::const_iterator it = group_map_.begin(); | |
| 930 it != group_map_.end(); ++it) { | |
| 931 if (it->second->IsStalledOnPoolMaxSockets(max_sockets_per_group_)) | |
| 932 return true; | |
| 933 } | |
| 934 return false; | |
| 935 } | |
| 936 | |
| 937 void ClientSocketPoolBaseHelper::RemoveConnectJob(ConnectJob* job, | 974 void ClientSocketPoolBaseHelper::RemoveConnectJob(ConnectJob* job, |
| 938 Group* group) { | 975 Group* group) { |
| 939 CHECK_GT(connecting_socket_count_, 0); | 976 CHECK_GT(connecting_socket_count_, 0); |
| 940 connecting_socket_count_--; | 977 connecting_socket_count_--; |
| 941 | 978 |
| 942 DCHECK(group); | 979 DCHECK(group); |
| 943 DCHECK(ContainsKey(group->jobs(), job)); | 980 DCHECK(ContainsKey(group->jobs(), job)); |
| 944 group->RemoveJob(job); | 981 group->RemoveJob(job); |
| 945 | 982 |
| 946 // If we've got no more jobs for this group, then we no longer need a | 983 // If we've got no more jobs for this group, then we no longer need a |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1094 if (group->IsEmpty()) | 1131 if (group->IsEmpty()) |
| 1095 RemoveGroup(i); | 1132 RemoveGroup(i); |
| 1096 | 1133 |
| 1097 return true; | 1134 return true; |
| 1098 } | 1135 } |
| 1099 } | 1136 } |
| 1100 | 1137 |
| 1101 return false; | 1138 return false; |
| 1102 } | 1139 } |
| 1103 | 1140 |
| 1104 bool ClientSocketPoolBaseHelper::CloseOneIdleConnectionInLayeredPool() { | 1141 bool ClientSocketPoolBaseHelper::CloseOneIdleConnectionInHigherLayeredPool() { |
| 1105 // This pool doesn't have any idle sockets. It's possible that a pool at a | 1142 // This pool doesn't have any idle sockets. It's possible that a pool at a |
| 1106 // higher layer is holding one of this sockets active, but it's actually idle. | 1143 // higher layer is holding one of this sockets active, but it's actually idle. |
| 1107 // Query the higher layers. | 1144 // Query the higher layers. |
| 1108 for (std::set<LayeredPool*>::const_iterator it = higher_layer_pools_.begin(); | 1145 for (std::set<HigherLayeredPool*>::const_iterator it = higher_pools_.begin(); |
| 1109 it != higher_layer_pools_.end(); ++it) { | 1146 it != higher_pools_.end(); ++it) { |
| 1110 if ((*it)->CloseOneIdleConnection()) | 1147 if ((*it)->CloseOneIdleConnection()) |
| 1111 return true; | 1148 return true; |
| 1112 } | 1149 } |
| 1113 return false; | 1150 return false; |
| 1114 } | 1151 } |
| 1115 | 1152 |
| 1116 void ClientSocketPoolBaseHelper::InvokeUserCallbackLater( | 1153 void ClientSocketPoolBaseHelper::InvokeUserCallbackLater( |
| 1117 ClientSocketHandle* handle, const CompletionCallback& callback, int rv) { | 1154 ClientSocketHandle* handle, const CompletionCallback& callback, int rv) { |
| 1118 CHECK(!ContainsKey(pending_callback_map_, handle)); | 1155 CHECK(!ContainsKey(pending_callback_map_, handle)); |
| 1119 pending_callback_map_[handle] = CallbackResultPair(callback, rv); | 1156 pending_callback_map_[handle] = CallbackResultPair(callback, rv); |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 1135 CompletionCallback callback = it->second.callback; | 1172 CompletionCallback callback = it->second.callback; |
| 1136 int result = it->second.result; | 1173 int result = it->second.result; |
| 1137 pending_callback_map_.erase(it); | 1174 pending_callback_map_.erase(it); |
| 1138 callback.Run(result); | 1175 callback.Run(result); |
| 1139 } | 1176 } |
| 1140 | 1177 |
| 1141 void ClientSocketPoolBaseHelper::TryToCloseSocketsInLayeredPools() { | 1178 void ClientSocketPoolBaseHelper::TryToCloseSocketsInLayeredPools() { |
| 1142 while (IsStalled()) { | 1179 while (IsStalled()) { |
| 1143 // Closing a socket will result in calling back into |this| to use the freed | 1180 // Closing a socket will result in calling back into |this| to use the freed |
| 1144 // socket slot, so nothing else is needed. | 1181 // socket slot, so nothing else is needed. |
| 1145 if (!CloseOneIdleConnectionInLayeredPool()) | 1182 if (!CloseOneIdleConnectionInHigherLayeredPool()) |
| 1146 return; | 1183 return; |
| 1147 } | 1184 } |
| 1148 } | 1185 } |
| 1149 | 1186 |
| 1150 ClientSocketPoolBaseHelper::Group::Group() | 1187 ClientSocketPoolBaseHelper::Group::Group() |
| 1151 : unassigned_job_count_(0), | 1188 : unassigned_job_count_(0), |
| 1152 active_socket_count_(0), | 1189 active_socket_count_(0), |
| 1153 weak_factory_(this) {} | 1190 weak_factory_(this) {} |
| 1154 | 1191 |
| 1155 ClientSocketPoolBaseHelper::Group::~Group() { | 1192 ClientSocketPoolBaseHelper::Group::~Group() { |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1242 STLDeleteElements(&jobs_); | 1279 STLDeleteElements(&jobs_); |
| 1243 unassigned_job_count_ = 0; | 1280 unassigned_job_count_ = 0; |
| 1244 | 1281 |
| 1245 // Cancel pending backup job. | 1282 // Cancel pending backup job. |
| 1246 weak_factory_.InvalidateWeakPtrs(); | 1283 weak_factory_.InvalidateWeakPtrs(); |
| 1247 } | 1284 } |
| 1248 | 1285 |
| 1249 } // namespace internal | 1286 } // namespace internal |
| 1250 | 1287 |
| 1251 } // namespace net | 1288 } // namespace net |
| OLD | NEW |