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 |