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. |
| 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 |
| 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 |