Chromium Code Reviews| 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 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 219 return false; | 219 return false; |
| 220 // So in order to be stalled, |this| must be using at least |max_sockets_| AND | 220 // So in order to be stalled, |this| must be using at least |max_sockets_| AND |
| 221 // |this| must have a request that is actually stalled on the global socket | 221 // |this| must have a request that is actually stalled on the global socket |
| 222 // limit. To find such a request, look for a group that has more requests | 222 // limit. To find such a request, look for a group that has more requests |
| 223 // than jobs AND where the number of sockets is less than | 223 // than jobs AND where the number of sockets is less than |
| 224 // |max_sockets_per_group_|. (If the number of sockets is equal to | 224 // |max_sockets_per_group_|. (If the number of sockets is equal to |
| 225 // |max_sockets_per_group_|, then the request is stalled on the group limit, | 225 // |max_sockets_per_group_|, then the request is stalled on the group limit, |
| 226 // which does not count.) | 226 // which does not count.) |
| 227 for (GroupMap::const_iterator it = group_map_.begin(); | 227 for (GroupMap::const_iterator it = group_map_.begin(); |
| 228 it != group_map_.end(); ++it) { | 228 it != group_map_.end(); ++it) { |
| 229 if (it->second->IsStalledOnPoolMaxSockets(max_sockets_per_group_)) | 229 if (it->second->CanUseAdditionalSocketSlot(max_sockets_per_group_)) |
| 230 return true; | 230 return true; |
| 231 } | 231 } |
| 232 return false; | 232 return false; |
| 233 } | 233 } |
| 234 | 234 |
| 235 void ClientSocketPoolBaseHelper::AddLowerLayeredPool( | 235 void ClientSocketPoolBaseHelper::AddLowerLayeredPool( |
| 236 LowerLayeredPool* lower_pool) { | 236 LowerLayeredPool* lower_pool) { |
| 237 DCHECK(pool_); | 237 DCHECK(pool_); |
| 238 CHECK(!ContainsKey(lower_pools_, lower_pool)); | 238 CHECK(!ContainsKey(lower_pools_, lower_pool)); |
| 239 lower_pools_.insert(lower_pool); | 239 lower_pools_.insert(lower_pool); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 271 if (rv != ERR_IO_PENDING) { | 271 if (rv != ERR_IO_PENDING) { |
| 272 request->net_log().EndEventWithNetErrorCode(NetLog::TYPE_SOCKET_POOL, rv); | 272 request->net_log().EndEventWithNetErrorCode(NetLog::TYPE_SOCKET_POOL, rv); |
| 273 CHECK(!request->handle()->is_initialized()); | 273 CHECK(!request->handle()->is_initialized()); |
| 274 request.reset(); | 274 request.reset(); |
| 275 } else { | 275 } else { |
| 276 group->InsertPendingRequest(request.Pass()); | 276 group->InsertPendingRequest(request.Pass()); |
| 277 // Have to do this asynchronously, as closing sockets in higher level pools | 277 // Have to do this asynchronously, as closing sockets in higher level pools |
| 278 // call back in to |this|, which will cause all sorts of fun and exciting | 278 // call back in to |this|, which will cause all sorts of fun and exciting |
| 279 // re-entrancy issues if the socket pool is doing something else at the | 279 // re-entrancy issues if the socket pool is doing something else at the |
| 280 // time. | 280 // time. |
| 281 if (group->IsStalledOnPoolMaxSockets(max_sockets_per_group_)) { | 281 if (group->CanUseAdditionalSocketSlot(max_sockets_per_group_)) { |
| 282 base::MessageLoop::current()->PostTask( | 282 base::MessageLoop::current()->PostTask( |
| 283 FROM_HERE, | 283 FROM_HERE, |
| 284 base::Bind( | 284 base::Bind( |
| 285 &ClientSocketPoolBaseHelper::TryToCloseSocketsInLayeredPools, | 285 &ClientSocketPoolBaseHelper::TryToCloseSocketsInLayeredPools, |
| 286 weak_factory_.GetWeakPtr())); | 286 weak_factory_.GetWeakPtr())); |
| 287 } | 287 } |
| 288 } | 288 } |
| 289 return rv; | 289 return rv; |
| 290 } | 290 } |
| 291 | 291 |
| (...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 571 if (group.HasConnectJobForHandle(handle)) { | 571 if (group.HasConnectJobForHandle(handle)) { |
| 572 // Just return the state of the farthest along ConnectJob for the first | 572 // Just return the state of the farthest along ConnectJob for the first |
| 573 // group.jobs().size() pending requests. | 573 // group.jobs().size() pending requests. |
| 574 LoadState max_state = LOAD_STATE_IDLE; | 574 LoadState max_state = LOAD_STATE_IDLE; |
| 575 for (const auto& job : group.jobs()) { | 575 for (const auto& job : group.jobs()) { |
| 576 max_state = std::max(max_state, job->GetLoadState()); | 576 max_state = std::max(max_state, job->GetLoadState()); |
| 577 } | 577 } |
| 578 return max_state; | 578 return max_state; |
| 579 } | 579 } |
| 580 | 580 |
| 581 if (group.IsStalledOnPoolMaxSockets(max_sockets_per_group_)) | 581 if (group.CanUseAdditionalSocketSlot(max_sockets_per_group_)) |
| 582 return LOAD_STATE_WAITING_FOR_STALLED_SOCKET_POOL; | 582 return LOAD_STATE_WAITING_FOR_STALLED_SOCKET_POOL; |
| 583 return LOAD_STATE_WAITING_FOR_AVAILABLE_SOCKET; | 583 return LOAD_STATE_WAITING_FOR_AVAILABLE_SOCKET; |
| 584 } | 584 } |
| 585 | 585 |
| 586 base::DictionaryValue* ClientSocketPoolBaseHelper::GetInfoAsValue( | 586 base::DictionaryValue* ClientSocketPoolBaseHelper::GetInfoAsValue( |
| 587 const std::string& name, const std::string& type) const { | 587 const std::string& name, const std::string& type) const { |
| 588 base::DictionaryValue* dict = new base::DictionaryValue(); | 588 base::DictionaryValue* dict = new base::DictionaryValue(); |
| 589 dict->SetString("name", name); | 589 dict->SetString("name", name); |
| 590 dict->SetString("type", type); | 590 dict->SetString("type", type); |
| 591 dict->SetInteger("handed_out_socket_count", handed_out_socket_count_); | 591 dict->SetInteger("handed_out_socket_count", handed_out_socket_count_); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 625 group_dict->Set("idle_sockets", idle_socket_list); | 625 group_dict->Set("idle_sockets", idle_socket_list); |
| 626 | 626 |
| 627 base::ListValue* connect_jobs_list = new base::ListValue(); | 627 base::ListValue* connect_jobs_list = new base::ListValue(); |
| 628 std::set<ConnectJob*>::const_iterator job = group->jobs().begin(); | 628 std::set<ConnectJob*>::const_iterator job = group->jobs().begin(); |
| 629 for (job = group->jobs().begin(); job != group->jobs().end(); job++) { | 629 for (job = group->jobs().begin(); job != group->jobs().end(); job++) { |
| 630 int source_id = (*job)->net_log().source().id; | 630 int source_id = (*job)->net_log().source().id; |
| 631 connect_jobs_list->Append(new base::FundamentalValue(source_id)); | 631 connect_jobs_list->Append(new base::FundamentalValue(source_id)); |
| 632 } | 632 } |
| 633 group_dict->Set("connect_jobs", connect_jobs_list); | 633 group_dict->Set("connect_jobs", connect_jobs_list); |
| 634 | 634 |
| 635 group_dict->SetBoolean("is_stalled", | 635 group_dict->SetBoolean("is_stalled", group->CanUseAdditionalSocketSlot( |
| 636 group->IsStalledOnPoolMaxSockets( | 636 max_sockets_per_group_)); |
| 637 max_sockets_per_group_)); | |
| 638 group_dict->SetBoolean("backup_job_timer_is_running", | 637 group_dict->SetBoolean("backup_job_timer_is_running", |
| 639 group->BackupJobTimerIsRunning()); | 638 group->BackupJobTimerIsRunning()); |
| 640 | 639 |
| 641 all_groups_dict->SetWithoutPathExpansion(it->first, group_dict); | 640 all_groups_dict->SetWithoutPathExpansion(it->first, group_dict); |
| 642 } | 641 } |
| 643 dict->Set("groups", all_groups_dict); | 642 dict->Set("groups", all_groups_dict); |
| 644 return dict; | 643 return dict; |
| 645 } | 644 } |
| 646 | 645 |
| 647 bool ClientSocketPoolBaseHelper::IdleSocket::IsUsable() const { | 646 bool ClientSocketPoolBaseHelper::IdleSocket::IsUsable() const { |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 829 std::string* group_name) const { | 828 std::string* group_name) const { |
| 830 CHECK((group && group_name) || (!group && !group_name)); | 829 CHECK((group && group_name) || (!group && !group_name)); |
| 831 Group* top_group = NULL; | 830 Group* top_group = NULL; |
| 832 const std::string* top_group_name = NULL; | 831 const std::string* top_group_name = NULL; |
| 833 bool has_stalled_group = false; | 832 bool has_stalled_group = false; |
| 834 for (GroupMap::const_iterator i = group_map_.begin(); | 833 for (GroupMap::const_iterator i = group_map_.begin(); |
| 835 i != group_map_.end(); ++i) { | 834 i != group_map_.end(); ++i) { |
| 836 Group* curr_group = i->second; | 835 Group* curr_group = i->second; |
| 837 if (!curr_group->has_pending_requests()) | 836 if (!curr_group->has_pending_requests()) |
| 838 continue; | 837 continue; |
| 839 if (curr_group->IsStalledOnPoolMaxSockets(max_sockets_per_group_)) { | 838 if (curr_group->CanUseAdditionalSocketSlot(max_sockets_per_group_)) { |
| 840 if (!group) | 839 if (!group) |
| 841 return true; | 840 return true; |
| 842 has_stalled_group = true; | 841 has_stalled_group = true; |
| 843 bool has_higher_priority = !top_group || | 842 bool has_higher_priority = !top_group || |
| 844 curr_group->TopPendingPriority() > top_group->TopPendingPriority(); | 843 curr_group->TopPendingPriority() > top_group->TopPendingPriority(); |
| 845 if (has_higher_priority) { | 844 if (has_higher_priority) { |
| 846 top_group = curr_group; | 845 top_group = curr_group; |
| 847 top_group_name = &i->first; | 846 top_group_name = &i->first; |
| 848 } | 847 } |
| 849 } | 848 } |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 913 connect_timing, request->handle(), base::TimeDelta(), | 912 connect_timing, request->handle(), base::TimeDelta(), |
| 914 group, request->net_log()); | 913 group, request->net_log()); |
| 915 } | 914 } |
| 916 request->net_log().EndEventWithNetErrorCode( | 915 request->net_log().EndEventWithNetErrorCode( |
| 917 NetLog::TYPE_SOCKET_POOL, result); | 916 NetLog::TYPE_SOCKET_POOL, result); |
| 918 InvokeUserCallbackLater(request->handle(), request->callback(), result); | 917 InvokeUserCallbackLater(request->handle(), request->callback(), result); |
| 919 } else { | 918 } else { |
| 920 RemoveConnectJob(job, group); | 919 RemoveConnectJob(job, group); |
| 921 } | 920 } |
| 922 if (!handed_out_socket) { | 921 if (!handed_out_socket) { |
| 923 OnAvailableSocketSlot(group_name, group); | 922 OnAvailableSocketSlot(group_name, group); |
|
mmenke
2015/03/04 22:48:43
The issue is this was resulting in always making a
| |
| 924 CheckForStalledSocketGroups(); | 923 CheckForStalledSocketGroups(); |
| 925 } | 924 } |
| 926 } | 925 } |
| 927 } | 926 } |
| 928 | 927 |
| 929 void ClientSocketPoolBaseHelper::OnIPAddressChanged() { | 928 void ClientSocketPoolBaseHelper::OnIPAddressChanged() { |
| 930 FlushWithError(ERR_NETWORK_CHANGED); | 929 FlushWithError(ERR_NETWORK_CHANGED); |
| 931 } | 930 } |
| 932 | 931 |
| 933 void ClientSocketPoolBaseHelper::FlushWithError(int error) { | 932 void ClientSocketPoolBaseHelper::FlushWithError(int error) { |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 953 RemoveGroup(group_name); | 952 RemoveGroup(group_name); |
| 954 } else if (group->has_pending_requests()) { | 953 } else if (group->has_pending_requests()) { |
| 955 ProcessPendingRequest(group_name, group); | 954 ProcessPendingRequest(group_name, group); |
| 956 } | 955 } |
| 957 } | 956 } |
| 958 | 957 |
| 959 void ClientSocketPoolBaseHelper::ProcessPendingRequest( | 958 void ClientSocketPoolBaseHelper::ProcessPendingRequest( |
| 960 const std::string& group_name, Group* group) { | 959 const std::string& group_name, Group* group) { |
| 961 const Request* next_request = group->GetNextPendingRequest(); | 960 const Request* next_request = group->GetNextPendingRequest(); |
| 962 DCHECK(next_request); | 961 DCHECK(next_request); |
| 962 | |
| 963 // If the group has no idle sockets, and can't make use of an additional slot, | |
| 964 // either because it's at the limit or because it's at the socket per group | |
| 965 // limit, then there's nothing to do. | |
| 966 if (group->idle_sockets().empty() && | |
| 967 !group->CanUseAdditionalSocketSlot(max_sockets_per_group_)) { | |
| 968 return; | |
| 969 } | |
| 970 | |
| 963 int rv = RequestSocketInternal(group_name, *next_request); | 971 int rv = RequestSocketInternal(group_name, *next_request); |
| 964 if (rv != ERR_IO_PENDING) { | 972 if (rv != ERR_IO_PENDING) { |
| 965 scoped_ptr<const Request> request = group->PopNextPendingRequest(); | 973 scoped_ptr<const Request> request = group->PopNextPendingRequest(); |
| 966 DCHECK(request); | 974 DCHECK(request); |
| 967 if (group->IsEmpty()) | 975 if (group->IsEmpty()) |
| 968 RemoveGroup(group_name); | 976 RemoveGroup(group_name); |
| 969 | 977 |
| 970 request->net_log().EndEventWithNetErrorCode(NetLog::TYPE_SOCKET_POOL, rv); | 978 request->net_log().EndEventWithNetErrorCode(NetLog::TYPE_SOCKET_POOL, rv); |
| 971 InvokeUserCallbackLater(request->handle(), request->callback(), rv); | 979 InvokeUserCallbackLater(request->handle(), request->callback(), rv); |
| 972 } | 980 } |
| (...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1322 pending_requests_.Erase(pointer); | 1330 pending_requests_.Erase(pointer); |
| 1323 // If there are no more requests, kill the backup timer. | 1331 // If there are no more requests, kill the backup timer. |
| 1324 if (pending_requests_.empty()) | 1332 if (pending_requests_.empty()) |
| 1325 backup_job_timer_.Stop(); | 1333 backup_job_timer_.Stop(); |
| 1326 return request.Pass(); | 1334 return request.Pass(); |
| 1327 } | 1335 } |
| 1328 | 1336 |
| 1329 } // namespace internal | 1337 } // namespace internal |
| 1330 | 1338 |
| 1331 } // namespace net | 1339 } // namespace net |
| OLD | NEW |