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 fewer than |max_sockets_| are in use, then clearly |this| is not |
| 260 // stalled. |
| 261 if ((handed_out_socket_count_ + connecting_socket_count_) < max_sockets_) |
| 262 return false; |
| 263 // So in order to be stalled, |this| must be using at least |max_sockets_| AND |
| 264 // |this| must have a request that is actually stalled on the global socket |
| 265 // limit. To find such a request, look for a group that has more requests |
| 266 // than jobs AND where the number of sockets is less than |
| 267 // |max_sockets_per_group_|. (If the number of sockets is equal to |
| 268 // |max_sockets_per_group_|, then the request is stalled on the group limit, |
| 269 // which does not count.) |
| 270 for (GroupMap::const_iterator it = group_map_.begin(); |
| 271 it != group_map_.end(); ++it) { |
| 272 if (it->second->IsStalledOnPoolMaxSockets(max_sockets_per_group_)) |
| 273 return true; |
| 274 } |
| 275 return false; |
245 } | 276 } |
246 | 277 |
247 void ClientSocketPoolBaseHelper::RemoveLayeredPool(LayeredPool* pool) { | 278 void ClientSocketPoolBaseHelper::AddLowerLayeredPool( |
248 CHECK(pool); | 279 LowerLayeredPool* lower_pool) { |
249 CHECK(ContainsKey(higher_layer_pools_, pool)); | 280 DCHECK(pool_); |
250 higher_layer_pools_.erase(pool); | 281 CHECK(!ContainsKey(lower_pools_, lower_pool)); |
| 282 lower_pools_.insert(lower_pool); |
| 283 lower_pool->AddHigherLayeredPool(pool_); |
| 284 } |
| 285 |
| 286 void ClientSocketPoolBaseHelper::AddHigherLayeredPool( |
| 287 HigherLayeredPool* higher_pool) { |
| 288 CHECK(higher_pool); |
| 289 CHECK(!ContainsKey(higher_pools_, higher_pool)); |
| 290 higher_pools_.insert(higher_pool); |
| 291 } |
| 292 |
| 293 void ClientSocketPoolBaseHelper::RemoveHigherLayeredPool( |
| 294 HigherLayeredPool* higher_pool) { |
| 295 CHECK(higher_pool); |
| 296 CHECK(ContainsKey(higher_pools_, higher_pool)); |
| 297 higher_pools_.erase(higher_pool); |
251 } | 298 } |
252 | 299 |
253 int ClientSocketPoolBaseHelper::RequestSocket( | 300 int ClientSocketPoolBaseHelper::RequestSocket( |
254 const std::string& group_name, | 301 const std::string& group_name, |
255 const Request* request) { | 302 const Request* request) { |
256 CHECK(!request->callback().is_null()); | 303 CHECK(!request->callback().is_null()); |
257 CHECK(request->handle()); | 304 CHECK(request->handle()); |
258 | 305 |
259 // Cleanup any timed-out idle sockets if no timer is used. | 306 // Cleanup any timed-out idle sockets if no timer is used. |
260 if (!use_cleanup_timer_) | 307 if (!use_cleanup_timer_) |
(...skipping 522 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
783 socket.reset(); | 830 socket.reset(); |
784 } | 831 } |
785 | 832 |
786 CheckForStalledSocketGroups(); | 833 CheckForStalledSocketGroups(); |
787 } | 834 } |
788 | 835 |
789 void ClientSocketPoolBaseHelper::CheckForStalledSocketGroups() { | 836 void ClientSocketPoolBaseHelper::CheckForStalledSocketGroups() { |
790 // If we have idle sockets, see if we can give one to the top-stalled group. | 837 // If we have idle sockets, see if we can give one to the top-stalled group. |
791 std::string top_group_name; | 838 std::string top_group_name; |
792 Group* top_group = NULL; | 839 Group* top_group = NULL; |
793 if (!FindTopStalledGroup(&top_group, &top_group_name)) | 840 if (!FindTopStalledGroup(&top_group, &top_group_name)) { |
| 841 // There may still be a stalled group in a lower level pool. |
| 842 for (std::set<LowerLayeredPool*>::iterator it = lower_pools_.begin(); |
| 843 it != lower_pools_.end(); |
| 844 ++it) { |
| 845 if ((*it)->IsStalled()) { |
| 846 CloseOneIdleSocket(); |
| 847 break; |
| 848 } |
| 849 } |
794 return; | 850 return; |
| 851 } |
795 | 852 |
796 if (ReachedMaxSocketsLimit()) { | 853 if (ReachedMaxSocketsLimit()) { |
797 if (idle_socket_count() > 0) { | 854 if (idle_socket_count() > 0) { |
798 CloseOneIdleSocket(); | 855 CloseOneIdleSocket(); |
799 } else { | 856 } else { |
800 // We can't activate more sockets since we're already at our global | 857 // We can't activate more sockets since we're already at our global |
801 // limit. | 858 // limit. |
802 return; | 859 return; |
803 } | 860 } |
804 } | 861 } |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
917 FlushWithError(ERR_NETWORK_CHANGED); | 974 FlushWithError(ERR_NETWORK_CHANGED); |
918 } | 975 } |
919 | 976 |
920 void ClientSocketPoolBaseHelper::FlushWithError(int error) { | 977 void ClientSocketPoolBaseHelper::FlushWithError(int error) { |
921 pool_generation_number_++; | 978 pool_generation_number_++; |
922 CancelAllConnectJobs(); | 979 CancelAllConnectJobs(); |
923 CloseIdleSockets(); | 980 CloseIdleSockets(); |
924 CancelAllRequestsWithError(error); | 981 CancelAllRequestsWithError(error); |
925 } | 982 } |
926 | 983 |
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, | 984 void ClientSocketPoolBaseHelper::RemoveConnectJob(ConnectJob* job, |
947 Group* group) { | 985 Group* group) { |
948 CHECK_GT(connecting_socket_count_, 0); | 986 CHECK_GT(connecting_socket_count_, 0); |
949 connecting_socket_count_--; | 987 connecting_socket_count_--; |
950 | 988 |
951 DCHECK(group); | 989 DCHECK(group); |
952 group->RemoveJob(job); | 990 group->RemoveJob(job); |
953 | 991 |
954 // If we've got no more jobs for this group, then we no longer need a | 992 // If we've got no more jobs for this group, then we no longer need a |
955 // backup job either. | 993 // backup job either. |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1101 if (group->IsEmpty()) | 1139 if (group->IsEmpty()) |
1102 RemoveGroup(i); | 1140 RemoveGroup(i); |
1103 | 1141 |
1104 return true; | 1142 return true; |
1105 } | 1143 } |
1106 } | 1144 } |
1107 | 1145 |
1108 return false; | 1146 return false; |
1109 } | 1147 } |
1110 | 1148 |
1111 bool ClientSocketPoolBaseHelper::CloseOneIdleConnectionInLayeredPool() { | 1149 bool ClientSocketPoolBaseHelper::CloseOneIdleConnectionInHigherLayeredPool() { |
1112 // This pool doesn't have any idle sockets. It's possible that a pool at a | 1150 // 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. | 1151 // higher layer is holding one of this sockets active, but it's actually idle. |
1114 // Query the higher layers. | 1152 // Query the higher layers. |
1115 for (std::set<LayeredPool*>::const_iterator it = higher_layer_pools_.begin(); | 1153 for (std::set<HigherLayeredPool*>::const_iterator it = higher_pools_.begin(); |
1116 it != higher_layer_pools_.end(); ++it) { | 1154 it != higher_pools_.end(); ++it) { |
1117 if ((*it)->CloseOneIdleConnection()) | 1155 if ((*it)->CloseOneIdleConnection()) |
1118 return true; | 1156 return true; |
1119 } | 1157 } |
1120 return false; | 1158 return false; |
1121 } | 1159 } |
1122 | 1160 |
1123 void ClientSocketPoolBaseHelper::InvokeUserCallbackLater( | 1161 void ClientSocketPoolBaseHelper::InvokeUserCallbackLater( |
1124 ClientSocketHandle* handle, const CompletionCallback& callback, int rv) { | 1162 ClientSocketHandle* handle, const CompletionCallback& callback, int rv) { |
1125 CHECK(!ContainsKey(pending_callback_map_, handle)); | 1163 CHECK(!ContainsKey(pending_callback_map_, handle)); |
1126 pending_callback_map_[handle] = CallbackResultPair(callback, rv); | 1164 pending_callback_map_[handle] = CallbackResultPair(callback, rv); |
(...skipping 15 matching lines...) Expand all Loading... |
1142 CompletionCallback callback = it->second.callback; | 1180 CompletionCallback callback = it->second.callback; |
1143 int result = it->second.result; | 1181 int result = it->second.result; |
1144 pending_callback_map_.erase(it); | 1182 pending_callback_map_.erase(it); |
1145 callback.Run(result); | 1183 callback.Run(result); |
1146 } | 1184 } |
1147 | 1185 |
1148 void ClientSocketPoolBaseHelper::TryToCloseSocketsInLayeredPools() { | 1186 void ClientSocketPoolBaseHelper::TryToCloseSocketsInLayeredPools() { |
1149 while (IsStalled()) { | 1187 while (IsStalled()) { |
1150 // Closing a socket will result in calling back into |this| to use the freed | 1188 // Closing a socket will result in calling back into |this| to use the freed |
1151 // socket slot, so nothing else is needed. | 1189 // socket slot, so nothing else is needed. |
1152 if (!CloseOneIdleConnectionInLayeredPool()) | 1190 if (!CloseOneIdleConnectionInHigherLayeredPool()) |
1153 return; | 1191 return; |
1154 } | 1192 } |
1155 } | 1193 } |
1156 | 1194 |
1157 ClientSocketPoolBaseHelper::Group::Group() | 1195 ClientSocketPoolBaseHelper::Group::Group() |
1158 : unassigned_job_count_(0), | 1196 : unassigned_job_count_(0), |
1159 active_socket_count_(0), | 1197 active_socket_count_(0), |
1160 weak_factory_(this) {} | 1198 weak_factory_(this) {} |
1161 | 1199 |
1162 ClientSocketPoolBaseHelper::Group::~Group() { | 1200 ClientSocketPoolBaseHelper::Group::~Group() { |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1257 STLDeleteElements(&jobs_); | 1295 STLDeleteElements(&jobs_); |
1258 unassigned_job_count_ = 0; | 1296 unassigned_job_count_ = 0; |
1259 | 1297 |
1260 // Cancel pending backup job. | 1298 // Cancel pending backup job. |
1261 weak_factory_.InvalidateWeakPtrs(); | 1299 weak_factory_.InvalidateWeakPtrs(); |
1262 } | 1300 } |
1263 | 1301 |
1264 } // namespace internal | 1302 } // namespace internal |
1265 | 1303 |
1266 } // namespace net | 1304 } // namespace net |
OLD | NEW |