Chromium Code Reviews| 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 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 239 request.net_log().BeginEvent( | 239 request.net_log().BeginEvent( |
| 240 NetLog::TYPE_SOCKET_POOL_CONNECTING_N_SOCKETS, | 240 NetLog::TYPE_SOCKET_POOL_CONNECTING_N_SOCKETS, |
| 241 make_scoped_refptr(new NetLogIntegerParameter( | 241 make_scoped_refptr(new NetLogIntegerParameter( |
| 242 "num_sockets", num_sockets))); | 242 "num_sockets", num_sockets))); |
| 243 | 243 |
| 244 Group* group = GetOrCreateGroup(group_name); | 244 Group* group = GetOrCreateGroup(group_name); |
| 245 | 245 |
| 246 for (int num_iterations_left = num_sockets; | 246 for (int num_iterations_left = num_sockets; |
| 247 group->NumActiveSocketSlots() < num_sockets && | 247 group->NumActiveSocketSlots() < num_sockets && |
| 248 num_iterations_left > 0 ; num_iterations_left--) { | 248 num_iterations_left > 0 ; num_iterations_left--) { |
| 249 int rv = RequestSocketInternal(group_name, &request); | 249 int rv = RequestSocketInternal(group_name, &request); |
|
willchan no longer on Chromium
2010/12/02 01:58:07
Should I special case ERR_PRECONNECT_MAX_SOCKET_LI
Mike Belshe
2010/12/02 02:46:48
It's up to you. Maybe add a TODO
| |
| 250 if (rv < 0 && rv != ERR_IO_PENDING) { | 250 if (rv < 0 && rv != ERR_IO_PENDING) { |
| 251 // We're encountering a synchronous error. Give up. | 251 // We're encountering a synchronous error. Give up. |
| 252 break; | 252 break; |
| 253 } | 253 } |
| 254 } | 254 } |
| 255 | 255 |
| 256 if (group->IsEmpty()) | 256 if (group->IsEmpty()) |
| 257 RemoveGroup(group_name); | 257 RemoveGroup(group_name); |
| 258 | 258 |
| 259 request.net_log().EndEvent( | 259 request.net_log().EndEvent( |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 279 | 279 |
| 280 // Can we make another active socket now? | 280 // Can we make another active socket now? |
| 281 if (!group->HasAvailableSocketSlot(max_sockets_per_group_)) { | 281 if (!group->HasAvailableSocketSlot(max_sockets_per_group_)) { |
| 282 request->net_log().AddEvent( | 282 request->net_log().AddEvent( |
| 283 NetLog::TYPE_SOCKET_POOL_STALLED_MAX_SOCKETS_PER_GROUP, NULL); | 283 NetLog::TYPE_SOCKET_POOL_STALLED_MAX_SOCKETS_PER_GROUP, NULL); |
| 284 return ERR_IO_PENDING; | 284 return ERR_IO_PENDING; |
| 285 } | 285 } |
| 286 | 286 |
| 287 if (ReachedMaxSocketsLimit()) { | 287 if (ReachedMaxSocketsLimit()) { |
| 288 if (idle_socket_count() > 0) { | 288 if (idle_socket_count() > 0) { |
| 289 CloseOneIdleSocket(); | 289 bool closed = CloseOneIdleSocketExceptInGroup(group); |
| 290 if (preconnecting && !closed) | |
| 291 return ERR_PRECONNECT_MAX_SOCKET_LIMIT; | |
| 290 } else { | 292 } else { |
| 291 // We could check if we really have a stalled group here, but it requires | 293 // We could check if we really have a stalled group here, but it requires |
| 292 // a scan of all groups, so just flip a flag here, and do the check later. | 294 // a scan of all groups, so just flip a flag here, and do the check later. |
| 293 request->net_log().AddEvent( | 295 request->net_log().AddEvent( |
| 294 NetLog::TYPE_SOCKET_POOL_STALLED_MAX_SOCKETS, NULL); | 296 NetLog::TYPE_SOCKET_POOL_STALLED_MAX_SOCKETS, NULL); |
| 295 return ERR_IO_PENDING; | 297 return ERR_IO_PENDING; |
| 296 } | 298 } |
| 297 } | 299 } |
| 298 | 300 |
| 299 // We couldn't find a socket to reuse, so allocate and connect a new one. | 301 // We couldn't find a socket to reuse, so allocate and connect a new one. |
| (...skipping 621 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 921 // Each connecting socket will eventually connect and be handed out. | 923 // Each connecting socket will eventually connect and be handed out. |
| 922 int total = handed_out_socket_count_ + connecting_socket_count_ + | 924 int total = handed_out_socket_count_ + connecting_socket_count_ + |
| 923 idle_socket_count(); | 925 idle_socket_count(); |
| 924 DCHECK_LE(total, max_sockets_); | 926 DCHECK_LE(total, max_sockets_); |
| 925 if (total < max_sockets_) | 927 if (total < max_sockets_) |
| 926 return false; | 928 return false; |
| 927 return true; | 929 return true; |
| 928 } | 930 } |
| 929 | 931 |
| 930 void ClientSocketPoolBaseHelper::CloseOneIdleSocket() { | 932 void ClientSocketPoolBaseHelper::CloseOneIdleSocket() { |
| 933 CloseOneIdleSocketExceptInGroup(NULL); | |
| 934 } | |
| 935 | |
| 936 bool ClientSocketPoolBaseHelper::CloseOneIdleSocketExceptInGroup( | |
| 937 const Group* exception_group) { | |
| 931 CHECK_GT(idle_socket_count(), 0); | 938 CHECK_GT(idle_socket_count(), 0); |
| 932 | 939 |
| 933 for (GroupMap::iterator i = group_map_.begin(); i != group_map_.end(); ++i) { | 940 for (GroupMap::iterator i = group_map_.begin(); i != group_map_.end(); ++i) { |
| 934 Group* group = i->second; | 941 Group* group = i->second; |
| 942 if (exception_group == group) | |
| 943 continue; | |
| 935 std::list<IdleSocket>* idle_sockets = group->mutable_idle_sockets(); | 944 std::list<IdleSocket>* idle_sockets = group->mutable_idle_sockets(); |
| 936 | 945 |
| 937 if (!idle_sockets->empty()) { | 946 if (!idle_sockets->empty()) { |
| 938 delete idle_sockets->front().socket; | 947 delete idle_sockets->front().socket; |
| 939 idle_sockets->pop_front(); | 948 idle_sockets->pop_front(); |
| 940 DecrementIdleCount(); | 949 DecrementIdleCount(); |
| 941 if (group->IsEmpty()) | 950 if (group->IsEmpty()) |
| 942 RemoveGroup(i); | 951 RemoveGroup(i); |
| 943 | 952 |
| 944 return; | 953 return true; |
| 945 } | 954 } |
| 946 } | 955 } |
| 947 | 956 |
| 948 LOG(DFATAL) << "No idle socket found to close!."; | 957 if (!exception_group) |
| 958 LOG(DFATAL) << "No idle socket found to close!."; | |
| 959 | |
| 960 return false; | |
| 949 } | 961 } |
| 950 | 962 |
| 951 void ClientSocketPoolBaseHelper::InvokeUserCallbackLater( | 963 void ClientSocketPoolBaseHelper::InvokeUserCallbackLater( |
| 952 ClientSocketHandle* handle, CompletionCallback* callback, int rv) { | 964 ClientSocketHandle* handle, CompletionCallback* callback, int rv) { |
| 953 CHECK(!ContainsKey(pending_callback_map_, handle)); | 965 CHECK(!ContainsKey(pending_callback_map_, handle)); |
| 954 pending_callback_map_[handle] = CallbackResultPair(callback, rv); | 966 pending_callback_map_[handle] = CallbackResultPair(callback, rv); |
| 955 MessageLoop::current()->PostTask( | 967 MessageLoop::current()->PostTask( |
| 956 FROM_HERE, | 968 FROM_HERE, |
| 957 method_factory_.NewRunnableMethod( | 969 method_factory_.NewRunnableMethod( |
| 958 &ClientSocketPoolBaseHelper::InvokeUserCallback, | 970 &ClientSocketPoolBaseHelper::InvokeUserCallback, |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1047 // Delete active jobs. | 1059 // Delete active jobs. |
| 1048 STLDeleteElements(&jobs_); | 1060 STLDeleteElements(&jobs_); |
| 1049 | 1061 |
| 1050 // Cancel pending backup job. | 1062 // Cancel pending backup job. |
| 1051 method_factory_.RevokeAll(); | 1063 method_factory_.RevokeAll(); |
| 1052 } | 1064 } |
| 1053 | 1065 |
| 1054 } // namespace internal | 1066 } // namespace internal |
| 1055 | 1067 |
| 1056 } // namespace net | 1068 } // namespace net |
| OLD | NEW |