OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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/message_loop.h" | 9 #include "base/message_loop.h" |
10 #include "base/metrics/stats_counters.h" | 10 #include "base/metrics/stats_counters.h" |
(...skipping 232 matching lines...) Loading... |
243 | 243 |
244 Group* group = GetOrCreateGroup(group_name); | 244 Group* group = GetOrCreateGroup(group_name); |
245 | 245 |
246 // RequestSocketsInternal() may delete the group. | 246 // RequestSocketsInternal() may delete the group. |
247 bool deleted_group = false; | 247 bool deleted_group = false; |
248 | 248 |
249 for (int num_iterations_left = num_sockets; | 249 for (int num_iterations_left = num_sockets; |
250 group->NumActiveSocketSlots() < num_sockets && | 250 group->NumActiveSocketSlots() < num_sockets && |
251 num_iterations_left > 0 ; num_iterations_left--) { | 251 num_iterations_left > 0 ; num_iterations_left--) { |
252 int rv = RequestSocketInternal(group_name, &request); | 252 int rv = RequestSocketInternal(group_name, &request); |
| 253 // TODO(willchan): Possibly check for ERR_PRECONNECT_MAX_SOCKET_LIMIT so we |
| 254 // can log it into the NetLog. |
253 if (rv < 0 && rv != ERR_IO_PENDING) { | 255 if (rv < 0 && rv != ERR_IO_PENDING) { |
254 // We're encountering a synchronous error. Give up. | 256 // We're encountering a synchronous error. Give up. |
255 if (!ContainsKey(group_map_, group_name)) | 257 if (!ContainsKey(group_map_, group_name)) |
256 deleted_group = true; | 258 deleted_group = true; |
257 break; | 259 break; |
258 } | 260 } |
259 if (!ContainsKey(group_map_, group_name)) { | 261 if (!ContainsKey(group_map_, group_name)) { |
260 // Unexpected. The group should only be getting deleted on synchronous | 262 // Unexpected. The group should only be getting deleted on synchronous |
261 // error. | 263 // error. |
262 NOTREACHED(); | 264 NOTREACHED(); |
(...skipping 28 matching lines...) Loading... |
291 | 293 |
292 // Can we make another active socket now? | 294 // Can we make another active socket now? |
293 if (!group->HasAvailableSocketSlot(max_sockets_per_group_)) { | 295 if (!group->HasAvailableSocketSlot(max_sockets_per_group_)) { |
294 request->net_log().AddEvent( | 296 request->net_log().AddEvent( |
295 NetLog::TYPE_SOCKET_POOL_STALLED_MAX_SOCKETS_PER_GROUP, NULL); | 297 NetLog::TYPE_SOCKET_POOL_STALLED_MAX_SOCKETS_PER_GROUP, NULL); |
296 return ERR_IO_PENDING; | 298 return ERR_IO_PENDING; |
297 } | 299 } |
298 | 300 |
299 if (ReachedMaxSocketsLimit()) { | 301 if (ReachedMaxSocketsLimit()) { |
300 if (idle_socket_count() > 0) { | 302 if (idle_socket_count() > 0) { |
301 CloseOneIdleSocket(); | 303 bool closed = CloseOneIdleSocketExceptInGroup(group); |
| 304 if (preconnecting && !closed) |
| 305 return ERR_PRECONNECT_MAX_SOCKET_LIMIT; |
302 } else { | 306 } else { |
303 // We could check if we really have a stalled group here, but it requires | 307 // We could check if we really have a stalled group here, but it requires |
304 // a scan of all groups, so just flip a flag here, and do the check later. | 308 // a scan of all groups, so just flip a flag here, and do the check later. |
305 request->net_log().AddEvent( | 309 request->net_log().AddEvent( |
306 NetLog::TYPE_SOCKET_POOL_STALLED_MAX_SOCKETS, NULL); | 310 NetLog::TYPE_SOCKET_POOL_STALLED_MAX_SOCKETS, NULL); |
307 return ERR_IO_PENDING; | 311 return ERR_IO_PENDING; |
308 } | 312 } |
309 } | 313 } |
310 | 314 |
311 // We couldn't find a socket to reuse, so allocate and connect a new one. | 315 // We couldn't find a socket to reuse, so allocate and connect a new one. |
(...skipping 621 matching lines...) Loading... |
933 // Each connecting socket will eventually connect and be handed out. | 937 // Each connecting socket will eventually connect and be handed out. |
934 int total = handed_out_socket_count_ + connecting_socket_count_ + | 938 int total = handed_out_socket_count_ + connecting_socket_count_ + |
935 idle_socket_count(); | 939 idle_socket_count(); |
936 DCHECK_LE(total, max_sockets_); | 940 DCHECK_LE(total, max_sockets_); |
937 if (total < max_sockets_) | 941 if (total < max_sockets_) |
938 return false; | 942 return false; |
939 return true; | 943 return true; |
940 } | 944 } |
941 | 945 |
942 void ClientSocketPoolBaseHelper::CloseOneIdleSocket() { | 946 void ClientSocketPoolBaseHelper::CloseOneIdleSocket() { |
| 947 CloseOneIdleSocketExceptInGroup(NULL); |
| 948 } |
| 949 |
| 950 bool ClientSocketPoolBaseHelper::CloseOneIdleSocketExceptInGroup( |
| 951 const Group* exception_group) { |
943 CHECK_GT(idle_socket_count(), 0); | 952 CHECK_GT(idle_socket_count(), 0); |
944 | 953 |
945 for (GroupMap::iterator i = group_map_.begin(); i != group_map_.end(); ++i) { | 954 for (GroupMap::iterator i = group_map_.begin(); i != group_map_.end(); ++i) { |
946 Group* group = i->second; | 955 Group* group = i->second; |
| 956 if (exception_group == group) |
| 957 continue; |
947 std::list<IdleSocket>* idle_sockets = group->mutable_idle_sockets(); | 958 std::list<IdleSocket>* idle_sockets = group->mutable_idle_sockets(); |
948 | 959 |
949 if (!idle_sockets->empty()) { | 960 if (!idle_sockets->empty()) { |
950 delete idle_sockets->front().socket; | 961 delete idle_sockets->front().socket; |
951 idle_sockets->pop_front(); | 962 idle_sockets->pop_front(); |
952 DecrementIdleCount(); | 963 DecrementIdleCount(); |
953 if (group->IsEmpty()) | 964 if (group->IsEmpty()) |
954 RemoveGroup(i); | 965 RemoveGroup(i); |
955 | 966 |
956 return; | 967 return true; |
957 } | 968 } |
958 } | 969 } |
959 | 970 |
960 LOG(DFATAL) << "No idle socket found to close!."; | 971 if (!exception_group) |
| 972 LOG(DFATAL) << "No idle socket found to close!."; |
| 973 |
| 974 return false; |
961 } | 975 } |
962 | 976 |
963 void ClientSocketPoolBaseHelper::InvokeUserCallbackLater( | 977 void ClientSocketPoolBaseHelper::InvokeUserCallbackLater( |
964 ClientSocketHandle* handle, CompletionCallback* callback, int rv) { | 978 ClientSocketHandle* handle, CompletionCallback* callback, int rv) { |
965 CHECK(!ContainsKey(pending_callback_map_, handle)); | 979 CHECK(!ContainsKey(pending_callback_map_, handle)); |
966 pending_callback_map_[handle] = CallbackResultPair(callback, rv); | 980 pending_callback_map_[handle] = CallbackResultPair(callback, rv); |
967 MessageLoop::current()->PostTask( | 981 MessageLoop::current()->PostTask( |
968 FROM_HERE, | 982 FROM_HERE, |
969 method_factory_.NewRunnableMethod( | 983 method_factory_.NewRunnableMethod( |
970 &ClientSocketPoolBaseHelper::InvokeUserCallback, | 984 &ClientSocketPoolBaseHelper::InvokeUserCallback, |
(...skipping 88 matching lines...) Loading... |
1059 // Delete active jobs. | 1073 // Delete active jobs. |
1060 STLDeleteElements(&jobs_); | 1074 STLDeleteElements(&jobs_); |
1061 | 1075 |
1062 // Cancel pending backup job. | 1076 // Cancel pending backup job. |
1063 method_factory_.RevokeAll(); | 1077 method_factory_.RevokeAll(); |
1064 } | 1078 } |
1065 | 1079 |
1066 } // namespace internal | 1080 } // namespace internal |
1067 | 1081 |
1068 } // namespace net | 1082 } // namespace net |
OLD | NEW |