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 <algorithm> | 7 #include <algorithm> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 272 | 272 |
| 273 void ClientSocketPoolBaseHelper::RemoveHigherLayeredPool( | 273 void ClientSocketPoolBaseHelper::RemoveHigherLayeredPool( |
| 274 HigherLayeredPool* higher_pool) { | 274 HigherLayeredPool* higher_pool) { |
| 275 CHECK(higher_pool); | 275 CHECK(higher_pool); |
| 276 CHECK(ContainsKey(higher_pools_, higher_pool)); | 276 CHECK(ContainsKey(higher_pools_, higher_pool)); |
| 277 higher_pools_.erase(higher_pool); | 277 higher_pools_.erase(higher_pool); |
| 278 } | 278 } |
| 279 | 279 |
| 280 int ClientSocketPoolBaseHelper::RequestSocket( | 280 int ClientSocketPoolBaseHelper::RequestSocket( |
| 281 const std::string& group_name, | 281 const std::string& group_name, |
| 282 std::unique_ptr<const Request> request) { | 282 std::unique_ptr<Request> request) { |
| 283 CHECK(!request->callback().is_null()); | 283 CHECK(!request->callback().is_null()); |
| 284 CHECK(request->handle()); | 284 CHECK(request->handle()); |
| 285 | 285 |
| 286 // Cleanup any timed-out idle sockets if no timer is used. | 286 // Cleanup any timed-out idle sockets if no timer is used. |
| 287 if (!use_cleanup_timer_) | 287 if (!use_cleanup_timer_) |
| 288 CleanupIdleSockets(false); | 288 CleanupIdleSockets(false); |
| 289 | 289 |
| 290 request->net_log().BeginEvent(NetLog::TYPE_SOCKET_POOL); | 290 request->net_log().BeginEvent(NetLog::TYPE_SOCKET_POOL); |
| 291 Group* group = GetOrCreateGroup(group_name); | 291 Group* group = GetOrCreateGroup(group_name); |
| 292 | 292 |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 520 return false; | 520 return false; |
| 521 } | 521 } |
| 522 | 522 |
| 523 // static | 523 // static |
| 524 void ClientSocketPoolBaseHelper::LogBoundConnectJobToRequest( | 524 void ClientSocketPoolBaseHelper::LogBoundConnectJobToRequest( |
| 525 const NetLog::Source& connect_job_source, const Request& request) { | 525 const NetLog::Source& connect_job_source, const Request& request) { |
| 526 request.net_log().AddEvent(NetLog::TYPE_SOCKET_POOL_BOUND_TO_CONNECT_JOB, | 526 request.net_log().AddEvent(NetLog::TYPE_SOCKET_POOL_BOUND_TO_CONNECT_JOB, |
| 527 connect_job_source.ToEventParametersCallback()); | 527 connect_job_source.ToEventParametersCallback()); |
| 528 } | 528 } |
| 529 | 529 |
| 530 void ClientSocketPoolBaseHelper::SetPriority(const std::string& group_name, | |
| 531 ClientSocketHandle* handle, | |
| 532 RequestPriority priority) { | |
| 533 PendingCallbackMap::iterator callback_it = pending_callback_map_.find(handle); | |
|
mmenke
2016/04/22 17:04:14
This seems a roundabout way of doing things, and w
mmenke
2016/04/22 17:05:19
does matter -> does not matter
Randy Smith (Not in Mondays)
2016/05/08 01:36:19
Sure, that's fine by me. Done.
I did it this way
Randy Smith (Not in Mondays)
2016/05/08 01:36:20
Acknowledged.
| |
| 534 // The Request has already completed and been destroyed; nothing to | |
| 535 // reprioritize. | |
| 536 if (callback_it != pending_callback_map_.end()) | |
| 537 return; | |
| 538 | |
| 539 DCHECK(ContainsKey(group_map_, group_name)); | |
| 540 | |
| 541 Group* group = GetOrCreateGroup(group_name); | |
| 542 std::unique_ptr<Request> request = group->FindAndRemovePendingRequest(handle); | |
| 543 DCHECK(request); | |
| 544 request->set_priority(priority); | |
|
mmenke
2016/04/22 17:04:14
Can we either DCHECK the priorities are not the sa
mmenke
2016/04/22 17:04:14
DCHECK(!request->ignore_limits())? Decreasing the
Randy Smith (Not in Mondays)
2016/05/08 01:36:19
Hmmm. I'm not certain how to do nothing if they a
Randy Smith (Not in Mondays)
2016/05/08 01:36:19
Done.
mmenke
2016/05/09 18:41:03
Looks like you're right. You could just DCHECK th
| |
| 545 group->InsertPendingRequest(std::move(request)); | |
| 546 } | |
| 547 | |
| 530 void ClientSocketPoolBaseHelper::CancelRequest( | 548 void ClientSocketPoolBaseHelper::CancelRequest( |
| 531 const std::string& group_name, ClientSocketHandle* handle) { | 549 const std::string& group_name, ClientSocketHandle* handle) { |
| 532 PendingCallbackMap::iterator callback_it = pending_callback_map_.find(handle); | 550 PendingCallbackMap::iterator callback_it = pending_callback_map_.find(handle); |
| 533 if (callback_it != pending_callback_map_.end()) { | 551 if (callback_it != pending_callback_map_.end()) { |
| 534 int result = callback_it->second.result; | 552 int result = callback_it->second.result; |
| 535 pending_callback_map_.erase(callback_it); | 553 pending_callback_map_.erase(callback_it); |
| 536 std::unique_ptr<StreamSocket> socket = handle->PassSocket(); | 554 std::unique_ptr<StreamSocket> socket = handle->PassSocket(); |
| 537 if (socket) { | 555 if (socket) { |
| 538 if (result != OK) | 556 if (result != OK) |
| 539 socket->Disconnect(); | 557 socket->Disconnect(); |
| 540 ReleaseSocket(handle->group_name(), std::move(socket), handle->id()); | 558 ReleaseSocket(handle->group_name(), std::move(socket), handle->id()); |
| 541 } | 559 } |
| 542 return; | 560 return; |
| 543 } | 561 } |
| 544 | 562 |
| 545 CHECK(ContainsKey(group_map_, group_name)); | 563 CHECK(ContainsKey(group_map_, group_name)); |
| 546 | 564 |
| 547 Group* group = GetOrCreateGroup(group_name); | 565 Group* group = GetOrCreateGroup(group_name); |
| 548 | 566 |
| 549 // Search pending_requests for matching handle. | 567 // Search pending_requests for matching handle. |
| 550 std::unique_ptr<const Request> request = | 568 std::unique_ptr<Request> request = group->FindAndRemovePendingRequest(handle); |
| 551 group->FindAndRemovePendingRequest(handle); | |
| 552 if (request) { | 569 if (request) { |
| 553 request->net_log().AddEvent(NetLog::TYPE_CANCELLED); | 570 request->net_log().AddEvent(NetLog::TYPE_CANCELLED); |
| 554 request->net_log().EndEvent(NetLog::TYPE_SOCKET_POOL); | 571 request->net_log().EndEvent(NetLog::TYPE_SOCKET_POOL); |
| 555 | 572 |
| 556 // We let the job run, unless we're at the socket limit and there is | 573 // We let the job run, unless we're at the socket limit and there is |
| 557 // not another request waiting on the job. | 574 // not another request waiting on the job. |
| 558 if (group->jobs().size() > group->pending_request_count() && | 575 if (group->jobs().size() > group->pending_request_count() && |
| 559 ReachedMaxSocketsLimit()) { | 576 ReachedMaxSocketsLimit()) { |
| 560 RemoveConnectJob(*group->jobs().begin(), group); | 577 RemoveConnectJob(*group->jobs().begin(), group); |
| 561 CheckForStalledSocketGroups(); | 578 CheckForStalledSocketGroups(); |
| (...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 897 // accessed. | 914 // accessed. |
| 898 BoundNetLog job_log = job->net_log(); | 915 BoundNetLog job_log = job->net_log(); |
| 899 LoadTimingInfo::ConnectTiming connect_timing = job->connect_timing(); | 916 LoadTimingInfo::ConnectTiming connect_timing = job->connect_timing(); |
| 900 | 917 |
| 901 // RemoveConnectJob(job, _) must be called by all branches below; | 918 // RemoveConnectJob(job, _) must be called by all branches below; |
| 902 // otherwise, |job| will be leaked. | 919 // otherwise, |job| will be leaked. |
| 903 | 920 |
| 904 if (result == OK) { | 921 if (result == OK) { |
| 905 DCHECK(socket.get()); | 922 DCHECK(socket.get()); |
| 906 RemoveConnectJob(job, group); | 923 RemoveConnectJob(job, group); |
| 907 std::unique_ptr<const Request> request = group->PopNextPendingRequest(); | 924 std::unique_ptr<Request> request = group->PopNextPendingRequest(); |
| 908 if (request) { | 925 if (request) { |
| 909 LogBoundConnectJobToRequest(job_log.source(), *request); | 926 LogBoundConnectJobToRequest(job_log.source(), *request); |
| 910 HandOutSocket(std::move(socket), ClientSocketHandle::UNUSED, | 927 HandOutSocket(std::move(socket), ClientSocketHandle::UNUSED, |
| 911 connect_timing, request->handle(), base::TimeDelta(), group, | 928 connect_timing, request->handle(), base::TimeDelta(), group, |
| 912 request->net_log()); | 929 request->net_log()); |
| 913 request->net_log().EndEvent(NetLog::TYPE_SOCKET_POOL); | 930 request->net_log().EndEvent(NetLog::TYPE_SOCKET_POOL); |
| 914 InvokeUserCallbackLater(request->handle(), request->callback(), result); | 931 InvokeUserCallbackLater(request->handle(), request->callback(), result); |
| 915 } else { | 932 } else { |
| 916 AddIdleSocket(std::move(socket), group); | 933 AddIdleSocket(std::move(socket), group); |
| 917 OnAvailableSocketSlot(group_name, group); | 934 OnAvailableSocketSlot(group_name, group); |
| 918 CheckForStalledSocketGroups(); | 935 CheckForStalledSocketGroups(); |
| 919 } | 936 } |
| 920 } else { | 937 } else { |
| 921 // If we got a socket, it must contain error information so pass that | 938 // If we got a socket, it must contain error information so pass that |
| 922 // up so that the caller can retrieve it. | 939 // up so that the caller can retrieve it. |
| 923 bool handed_out_socket = false; | 940 bool handed_out_socket = false; |
| 924 std::unique_ptr<const Request> request = group->PopNextPendingRequest(); | 941 std::unique_ptr<Request> request = group->PopNextPendingRequest(); |
| 925 if (request) { | 942 if (request) { |
| 926 LogBoundConnectJobToRequest(job_log.source(), *request); | 943 LogBoundConnectJobToRequest(job_log.source(), *request); |
| 927 job->GetAdditionalErrorState(request->handle()); | 944 job->GetAdditionalErrorState(request->handle()); |
| 928 RemoveConnectJob(job, group); | 945 RemoveConnectJob(job, group); |
| 929 if (socket.get()) { | 946 if (socket.get()) { |
| 930 handed_out_socket = true; | 947 handed_out_socket = true; |
| 931 HandOutSocket(std::move(socket), ClientSocketHandle::UNUSED, | 948 HandOutSocket(std::move(socket), ClientSocketHandle::UNUSED, |
| 932 connect_timing, request->handle(), base::TimeDelta(), | 949 connect_timing, request->handle(), base::TimeDelta(), |
| 933 group, request->net_log()); | 950 group, request->net_log()); |
| 934 } | 951 } |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 983 // If the group has no idle sockets, and can't make use of an additional slot, | 1000 // If the group has no idle sockets, and can't make use of an additional slot, |
| 984 // either because it's at the limit or because it's at the socket per group | 1001 // either because it's at the limit or because it's at the socket per group |
| 985 // limit, then there's nothing to do. | 1002 // limit, then there's nothing to do. |
| 986 if (group->idle_sockets().empty() && | 1003 if (group->idle_sockets().empty() && |
| 987 !group->CanUseAdditionalSocketSlot(max_sockets_per_group_)) { | 1004 !group->CanUseAdditionalSocketSlot(max_sockets_per_group_)) { |
| 988 return; | 1005 return; |
| 989 } | 1006 } |
| 990 | 1007 |
| 991 int rv = RequestSocketInternal(group_name, *next_request); | 1008 int rv = RequestSocketInternal(group_name, *next_request); |
| 992 if (rv != ERR_IO_PENDING) { | 1009 if (rv != ERR_IO_PENDING) { |
| 993 std::unique_ptr<const Request> request = group->PopNextPendingRequest(); | 1010 std::unique_ptr<Request> request = group->PopNextPendingRequest(); |
| 994 DCHECK(request); | 1011 DCHECK(request); |
| 995 if (group->IsEmpty()) | 1012 if (group->IsEmpty()) |
| 996 RemoveGroup(group_name); | 1013 RemoveGroup(group_name); |
| 997 | 1014 |
| 998 request->net_log().EndEventWithNetErrorCode(NetLog::TYPE_SOCKET_POOL, rv); | 1015 request->net_log().EndEventWithNetErrorCode(NetLog::TYPE_SOCKET_POOL, rv); |
| 999 InvokeUserCallbackLater(request->handle(), request->callback(), rv); | 1016 InvokeUserCallbackLater(request->handle(), request->callback(), rv); |
| 1000 } | 1017 } |
| 1001 } | 1018 } |
| 1002 | 1019 |
| 1003 void ClientSocketPoolBaseHelper::HandOutSocket( | 1020 void ClientSocketPoolBaseHelper::HandOutSocket( |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1059 } | 1076 } |
| 1060 } | 1077 } |
| 1061 DCHECK_EQ(0, connecting_socket_count_); | 1078 DCHECK_EQ(0, connecting_socket_count_); |
| 1062 } | 1079 } |
| 1063 | 1080 |
| 1064 void ClientSocketPoolBaseHelper::CancelAllRequestsWithError(int error) { | 1081 void ClientSocketPoolBaseHelper::CancelAllRequestsWithError(int error) { |
| 1065 for (GroupMap::iterator i = group_map_.begin(); i != group_map_.end();) { | 1082 for (GroupMap::iterator i = group_map_.begin(); i != group_map_.end();) { |
| 1066 Group* group = i->second; | 1083 Group* group = i->second; |
| 1067 | 1084 |
| 1068 while (true) { | 1085 while (true) { |
| 1069 std::unique_ptr<const Request> request = group->PopNextPendingRequest(); | 1086 std::unique_ptr<Request> request = group->PopNextPendingRequest(); |
| 1070 if (!request) | 1087 if (!request) |
| 1071 break; | 1088 break; |
| 1072 InvokeUserCallbackLater(request->handle(), request->callback(), error); | 1089 InvokeUserCallbackLater(request->handle(), request->callback(), error); |
| 1073 } | 1090 } |
| 1074 | 1091 |
| 1075 // Delete group if no longer needed. | 1092 // Delete group if no longer needed. |
| 1076 if (group->IsEmpty()) { | 1093 if (group->IsEmpty()) { |
| 1077 // RemoveGroup() will call .erase() which will invalidate the iterator, | 1094 // RemoveGroup() will call .erase() which will invalidate the iterator, |
| 1078 // but i will already have been incremented to a valid iterator before | 1095 // but i will already have been incremented to a valid iterator before |
| 1079 // RemoveGroup() is called. | 1096 // RemoveGroup() is called. |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1297 for (RequestQueue::Pointer pointer = pending_requests_.FirstMax(); | 1314 for (RequestQueue::Pointer pointer = pending_requests_.FirstMax(); |
| 1298 !pointer.is_null() && i < jobs_.size(); | 1315 !pointer.is_null() && i < jobs_.size(); |
| 1299 pointer = pending_requests_.GetNextTowardsLastMin(pointer), ++i) { | 1316 pointer = pending_requests_.GetNextTowardsLastMin(pointer), ++i) { |
| 1300 if (pointer.value()->handle() == handle) | 1317 if (pointer.value()->handle() == handle) |
| 1301 return true; | 1318 return true; |
| 1302 } | 1319 } |
| 1303 return false; | 1320 return false; |
| 1304 } | 1321 } |
| 1305 | 1322 |
| 1306 void ClientSocketPoolBaseHelper::Group::InsertPendingRequest( | 1323 void ClientSocketPoolBaseHelper::Group::InsertPendingRequest( |
| 1307 std::unique_ptr<const Request> request) { | 1324 std::unique_ptr<Request> request) { |
| 1308 // This value must be cached before we release |request|. | 1325 // This value must be cached before we release |request|. |
| 1309 RequestPriority priority = request->priority(); | 1326 RequestPriority priority = request->priority(); |
| 1310 if (request->respect_limits() == ClientSocketPool::RespectLimits::DISABLED) { | 1327 if (request->respect_limits() == ClientSocketPool::RespectLimits::DISABLED) { |
| 1311 // Put requests with RespectLimits::DISABLED (which should have | 1328 // Put requests with RespectLimits::DISABLED (which should have |
| 1312 // priority == MAXIMUM_PRIORITY) ahead of other requests with | 1329 // priority == MAXIMUM_PRIORITY) ahead of other requests with |
| 1313 // MAXIMUM_PRIORITY. | 1330 // MAXIMUM_PRIORITY. |
| 1314 DCHECK_EQ(priority, MAXIMUM_PRIORITY); | 1331 DCHECK_EQ(priority, MAXIMUM_PRIORITY); |
| 1315 pending_requests_.InsertAtFront(request.release(), priority); | 1332 pending_requests_.InsertAtFront(request.release(), priority); |
| 1316 } else { | 1333 } else { |
| 1317 pending_requests_.Insert(request.release(), priority); | 1334 pending_requests_.Insert(request.release(), priority); |
| 1318 } | 1335 } |
| 1319 } | 1336 } |
| 1320 | 1337 |
| 1321 std::unique_ptr<const ClientSocketPoolBaseHelper::Request> | 1338 std::unique_ptr<ClientSocketPoolBaseHelper::Request> |
| 1322 ClientSocketPoolBaseHelper::Group::PopNextPendingRequest() { | 1339 ClientSocketPoolBaseHelper::Group::PopNextPendingRequest() { |
| 1323 if (pending_requests_.empty()) | 1340 if (pending_requests_.empty()) |
| 1324 return std::unique_ptr<const ClientSocketPoolBaseHelper::Request>(); | 1341 return std::unique_ptr<ClientSocketPoolBaseHelper::Request>(); |
| 1325 return RemovePendingRequest(pending_requests_.FirstMax()); | 1342 return RemovePendingRequest(pending_requests_.FirstMax()); |
| 1326 } | 1343 } |
| 1327 | 1344 |
| 1328 std::unique_ptr<const ClientSocketPoolBaseHelper::Request> | 1345 std::unique_ptr<ClientSocketPoolBaseHelper::Request> |
| 1329 ClientSocketPoolBaseHelper::Group::FindAndRemovePendingRequest( | 1346 ClientSocketPoolBaseHelper::Group::FindAndRemovePendingRequest( |
| 1330 ClientSocketHandle* handle) { | 1347 ClientSocketHandle* handle) { |
| 1331 for (RequestQueue::Pointer pointer = pending_requests_.FirstMax(); | 1348 for (RequestQueue::Pointer pointer = pending_requests_.FirstMax(); |
| 1332 !pointer.is_null(); | 1349 !pointer.is_null(); |
| 1333 pointer = pending_requests_.GetNextTowardsLastMin(pointer)) { | 1350 pointer = pending_requests_.GetNextTowardsLastMin(pointer)) { |
| 1334 if (pointer.value()->handle() == handle) { | 1351 if (pointer.value()->handle() == handle) { |
| 1335 std::unique_ptr<const Request> request = RemovePendingRequest(pointer); | 1352 std::unique_ptr<Request> request = RemovePendingRequest(pointer); |
| 1336 return request; | 1353 return request; |
| 1337 } | 1354 } |
| 1338 } | 1355 } |
| 1339 return std::unique_ptr<const ClientSocketPoolBaseHelper::Request>(); | 1356 return std::unique_ptr<ClientSocketPoolBaseHelper::Request>(); |
| 1340 } | 1357 } |
| 1341 | 1358 |
| 1342 std::unique_ptr<const ClientSocketPoolBaseHelper::Request> | 1359 std::unique_ptr<ClientSocketPoolBaseHelper::Request> |
| 1343 ClientSocketPoolBaseHelper::Group::RemovePendingRequest( | 1360 ClientSocketPoolBaseHelper::Group::RemovePendingRequest( |
| 1344 const RequestQueue::Pointer& pointer) { | 1361 const RequestQueue::Pointer& pointer) { |
| 1345 // TODO(eroman): Temporary for debugging http://crbug.com/467797. | 1362 // TODO(eroman): Temporary for debugging http://crbug.com/467797. |
| 1346 CHECK(!pointer.is_null()); | 1363 CHECK(!pointer.is_null()); |
| 1347 std::unique_ptr<const Request> request(pointer.value()); | 1364 std::unique_ptr<Request> request(pointer.value()); |
| 1348 pending_requests_.Erase(pointer); | 1365 pending_requests_.Erase(pointer); |
| 1349 // If there are no more requests, kill the backup timer. | 1366 // If there are no more requests, kill the backup timer. |
| 1350 if (pending_requests_.empty()) | 1367 if (pending_requests_.empty()) |
| 1351 backup_job_timer_.Stop(); | 1368 backup_job_timer_.Stop(); |
| 1352 request->CrashIfInvalid(); | 1369 request->CrashIfInvalid(); |
| 1353 return request; | 1370 return request; |
| 1354 } | 1371 } |
| 1355 | 1372 |
| 1356 } // namespace internal | 1373 } // namespace internal |
| 1357 | 1374 |
| 1358 } // namespace net | 1375 } // namespace net |
| OLD | NEW |