| 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 432 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 443 connect_job_factory_->NewConnectJob(group_name, request, this)); | 443 connect_job_factory_->NewConnectJob(group_name, request, this)); |
| 444 | 444 |
| 445 int rv = connect_job->Connect(); | 445 int rv = connect_job->Connect(); |
| 446 if (rv == OK) { | 446 if (rv == OK) { |
| 447 LogBoundConnectJobToRequest(connect_job->net_log().source(), request); | 447 LogBoundConnectJobToRequest(connect_job->net_log().source(), request); |
| 448 if (!preconnecting) { | 448 if (!preconnecting) { |
| 449 HandOutSocket(connect_job->PassSocket(), ClientSocketHandle::UNUSED, | 449 HandOutSocket(connect_job->PassSocket(), ClientSocketHandle::UNUSED, |
| 450 connect_job->connect_timing(), handle, base::TimeDelta(), | 450 connect_job->connect_timing(), handle, base::TimeDelta(), |
| 451 group, request.net_log()); | 451 group, request.net_log()); |
| 452 } else { | 452 } else { |
| 453 AddIdleSocket(connect_job->PassSocket(), group); | 453 AddIdleSocket(connect_job->PassSocket(), group, |
| 454 connect_job->connect_timing()); |
| 454 } | 455 } |
| 455 } else if (rv == ERR_IO_PENDING) { | 456 } else if (rv == ERR_IO_PENDING) { |
| 456 // If we don't have any sockets in this group, set a timer for potentially | 457 // If we don't have any sockets in this group, set a timer for potentially |
| 457 // creating a new one. If the SYN is lost, this backup socket may complete | 458 // creating a new one. If the SYN is lost, this backup socket may complete |
| 458 // before the slow socket, improving end user latency. | 459 // before the slow socket, improving end user latency. |
| 459 if (connect_backup_jobs_enabled_ && group->IsEmpty()) { | 460 if (connect_backup_jobs_enabled_ && group->IsEmpty()) { |
| 460 group->StartBackupJobTimer(group_name, this); | 461 group->StartBackupJobTimer(group_name, this); |
| 461 } | 462 } |
| 462 | 463 |
| 463 connecting_socket_count_++; | 464 connecting_socket_count_++; |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 535 | 536 |
| 536 RecordIdleSocketFate(idle_socket.socket->WasEverUsed() | 537 RecordIdleSocketFate(idle_socket.socket->WasEverUsed() |
| 537 ? IDLE_SOCKET_FATE_REUSE_REUSED | 538 ? IDLE_SOCKET_FATE_REUSE_REUSED |
| 538 : IDLE_SOCKET_FATE_REUSE_UNUSED); | 539 : IDLE_SOCKET_FATE_REUSE_UNUSED); |
| 539 // If this socket took multiple attempts to obtain, don't report those | 540 // If this socket took multiple attempts to obtain, don't report those |
| 540 // every time it's reused, just to the first user. | 541 // every time it's reused, just to the first user. |
| 541 if (idle_socket.socket->WasEverUsed()) | 542 if (idle_socket.socket->WasEverUsed()) |
| 542 idle_socket.socket->ClearConnectionAttempts(); | 543 idle_socket.socket->ClearConnectionAttempts(); |
| 543 | 544 |
| 544 HandOutSocket(std::unique_ptr<StreamSocket>(idle_socket.socket), reuse_type, | 545 HandOutSocket(std::unique_ptr<StreamSocket>(idle_socket.socket), reuse_type, |
| 545 LoadTimingInfo::ConnectTiming(), request.handle(), idle_time, | 546 idle_socket.connect_timing, request.handle(), idle_time, |
| 546 group, request.net_log()); | 547 group, request.net_log()); |
| 547 return true; | 548 return true; |
| 548 } | 549 } |
| 549 | 550 |
| 550 return false; | 551 return false; |
| 551 } | 552 } |
| 552 | 553 |
| 553 // static | 554 // static |
| 554 void ClientSocketPoolBaseHelper::LogBoundConnectJobToRequest( | 555 void ClientSocketPoolBaseHelper::LogBoundConnectJobToRequest( |
| 555 const NetLogSource& connect_job_source, | 556 const NetLogSource& connect_job_source, |
| 556 const Request& request) { | 557 const Request& request) { |
| 557 request.net_log().AddEvent(NetLogEventType::SOCKET_POOL_BOUND_TO_CONNECT_JOB, | 558 request.net_log().AddEvent(NetLogEventType::SOCKET_POOL_BOUND_TO_CONNECT_JOB, |
| 558 connect_job_source.ToEventParametersCallback()); | 559 connect_job_source.ToEventParametersCallback()); |
| 559 } | 560 } |
| 560 | 561 |
| 561 void ClientSocketPoolBaseHelper::CancelRequest( | 562 void ClientSocketPoolBaseHelper::CancelRequest( |
| 562 const std::string& group_name, ClientSocketHandle* handle) { | 563 const std::string& group_name, ClientSocketHandle* handle) { |
| 563 PendingCallbackMap::iterator callback_it = pending_callback_map_.find(handle); | 564 PendingCallbackMap::iterator callback_it = pending_callback_map_.find(handle); |
| 564 if (callback_it != pending_callback_map_.end()) { | 565 if (callback_it != pending_callback_map_.end()) { |
| 565 int result = callback_it->second.result; | 566 int result = callback_it->second.result; |
| 566 pending_callback_map_.erase(callback_it); | 567 pending_callback_map_.erase(callback_it); |
| 567 std::unique_ptr<StreamSocket> socket = handle->PassSocket(); | 568 std::unique_ptr<StreamSocket> socket = handle->PassSocket(); |
| 568 if (socket) { | 569 if (socket) { |
| 569 if (result != OK) | 570 if (result != OK) |
| 570 socket->Disconnect(); | 571 socket->Disconnect(); |
| 571 ReleaseSocket(handle->group_name(), std::move(socket), handle->id()); | 572 ReleaseSocket(handle->group_name(), std::move(socket), handle->id(), |
| 573 handle->connect_timing()); |
| 572 } | 574 } |
| 573 return; | 575 return; |
| 574 } | 576 } |
| 575 | 577 |
| 576 CHECK(base::ContainsKey(group_map_, group_name)); | 578 CHECK(base::ContainsKey(group_map_, group_name)); |
| 577 | 579 |
| 578 Group* group = GetOrCreateGroup(group_name); | 580 Group* group = GetOrCreateGroup(group_name); |
| 579 | 581 |
| 580 // Search pending_requests for matching handle. | 582 // Search pending_requests for matching handle. |
| 581 std::unique_ptr<const Request> request = | 583 std::unique_ptr<const Request> request = |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 793 ++idle_socket_count_; | 795 ++idle_socket_count_; |
| 794 } | 796 } |
| 795 | 797 |
| 796 void ClientSocketPoolBaseHelper::DecrementIdleCount() { | 798 void ClientSocketPoolBaseHelper::DecrementIdleCount() { |
| 797 --idle_socket_count_; | 799 --idle_socket_count_; |
| 798 } | 800 } |
| 799 | 801 |
| 800 void ClientSocketPoolBaseHelper::ReleaseSocket( | 802 void ClientSocketPoolBaseHelper::ReleaseSocket( |
| 801 const std::string& group_name, | 803 const std::string& group_name, |
| 802 std::unique_ptr<StreamSocket> socket, | 804 std::unique_ptr<StreamSocket> socket, |
| 803 int id) { | 805 int id, |
| 806 const LoadTimingInfo::ConnectTiming& connect_timing) { |
| 804 GroupMap::iterator i = group_map_.find(group_name); | 807 GroupMap::iterator i = group_map_.find(group_name); |
| 805 CHECK(i != group_map_.end()); | 808 CHECK(i != group_map_.end()); |
| 806 | 809 |
| 807 Group* group = i->second; | 810 Group* group = i->second; |
| 808 | 811 |
| 809 CHECK_GT(handed_out_socket_count_, 0); | 812 CHECK_GT(handed_out_socket_count_, 0); |
| 810 handed_out_socket_count_--; | 813 handed_out_socket_count_--; |
| 811 | 814 |
| 812 CHECK_GT(group->active_socket_count(), 0); | 815 CHECK_GT(group->active_socket_count(), 0); |
| 813 group->DecrementActiveSocketCount(); | 816 group->DecrementActiveSocketCount(); |
| 814 | 817 |
| 815 const bool can_reuse = socket->IsConnectedAndIdle() && | 818 const bool can_reuse = socket->IsConnectedAndIdle() && |
| 816 id == pool_generation_number_; | 819 id == pool_generation_number_; |
| 817 if (can_reuse) { | 820 if (can_reuse) { |
| 818 // Add it to the idle list. | 821 // Add it to the idle list. |
| 819 AddIdleSocket(std::move(socket), group); | 822 AddIdleSocket(std::move(socket), group, connect_timing); |
| 820 OnAvailableSocketSlot(group_name, group); | 823 OnAvailableSocketSlot(group_name, group); |
| 821 } else { | 824 } else { |
| 822 socket.reset(); | 825 socket.reset(); |
| 823 RecordIdleSocketFate(IDLE_SOCKET_FATE_RELEASE_UNUSABLE); | 826 RecordIdleSocketFate(IDLE_SOCKET_FATE_RELEASE_UNUSABLE); |
| 824 } | 827 } |
| 825 | 828 |
| 826 CheckForStalledSocketGroups(); | 829 CheckForStalledSocketGroups(); |
| 827 } | 830 } |
| 828 | 831 |
| 829 void ClientSocketPoolBaseHelper::CheckForStalledSocketGroups() { | 832 void ClientSocketPoolBaseHelper::CheckForStalledSocketGroups() { |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 922 RemoveConnectJob(job, group); | 925 RemoveConnectJob(job, group); |
| 923 std::unique_ptr<const Request> request = group->PopNextPendingRequest(); | 926 std::unique_ptr<const Request> request = group->PopNextPendingRequest(); |
| 924 if (request) { | 927 if (request) { |
| 925 LogBoundConnectJobToRequest(job_log.source(), *request); | 928 LogBoundConnectJobToRequest(job_log.source(), *request); |
| 926 HandOutSocket(std::move(socket), ClientSocketHandle::UNUSED, | 929 HandOutSocket(std::move(socket), ClientSocketHandle::UNUSED, |
| 927 connect_timing, request->handle(), base::TimeDelta(), group, | 930 connect_timing, request->handle(), base::TimeDelta(), group, |
| 928 request->net_log()); | 931 request->net_log()); |
| 929 request->net_log().EndEvent(NetLogEventType::SOCKET_POOL); | 932 request->net_log().EndEvent(NetLogEventType::SOCKET_POOL); |
| 930 InvokeUserCallbackLater(request->handle(), request->callback(), result); | 933 InvokeUserCallbackLater(request->handle(), request->callback(), result); |
| 931 } else { | 934 } else { |
| 932 AddIdleSocket(std::move(socket), group); | 935 AddIdleSocket(std::move(socket), group, connect_timing); |
| 933 OnAvailableSocketSlot(group_name, group); | 936 OnAvailableSocketSlot(group_name, group); |
| 934 CheckForStalledSocketGroups(); | 937 CheckForStalledSocketGroups(); |
| 935 } | 938 } |
| 936 } else { | 939 } else { |
| 937 // If we got a socket, it must contain error information so pass that | 940 // If we got a socket, it must contain error information so pass that |
| 938 // up so that the caller can retrieve it. | 941 // up so that the caller can retrieve it. |
| 939 bool handed_out_socket = false; | 942 bool handed_out_socket = false; |
| 940 std::unique_ptr<const Request> request = group->PopNextPendingRequest(); | 943 std::unique_ptr<const Request> request = group->PopNextPendingRequest(); |
| 941 if (request) { | 944 if (request) { |
| 942 LogBoundConnectJobToRequest(job_log.source(), *request); | 945 LogBoundConnectJobToRequest(job_log.source(), *request); |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1034 | 1037 |
| 1035 if (reuse_type == ClientSocketHandle::REUSED_IDLE) { | 1038 if (reuse_type == ClientSocketHandle::REUSED_IDLE) { |
| 1036 net_log.AddEvent( | 1039 net_log.AddEvent( |
| 1037 NetLogEventType::SOCKET_POOL_REUSED_AN_EXISTING_SOCKET, | 1040 NetLogEventType::SOCKET_POOL_REUSED_AN_EXISTING_SOCKET, |
| 1038 NetLog::IntCallback("idle_ms", | 1041 NetLog::IntCallback("idle_ms", |
| 1039 static_cast<int>(idle_time.InMilliseconds()))); | 1042 static_cast<int>(idle_time.InMilliseconds()))); |
| 1040 | 1043 |
| 1041 UMA_HISTOGRAM_COUNTS_1000("Net.Socket.IdleSocketReuseTime", | 1044 UMA_HISTOGRAM_COUNTS_1000("Net.Socket.IdleSocketReuseTime", |
| 1042 idle_time.InSeconds()); | 1045 idle_time.InSeconds()); |
| 1043 UMA_HISTOGRAM_TIMES( | 1046 UMA_HISTOGRAM_TIMES( |
| 1044 "Net.Socket.IdleSocketTimeSaving", | 1047 "Net.Socket.IdleSocketTimeSaving2", |
| 1045 connect_timing.connect_end - connect_timing.connect_start); | 1048 connect_timing.connect_end - connect_timing.connect_start); |
| 1046 } | 1049 } |
| 1047 | 1050 |
| 1048 if (reuse_type != ClientSocketHandle::UNUSED) { | 1051 if (reuse_type != ClientSocketHandle::UNUSED) { |
| 1049 // The socket being handed out is no longer considered idle, but was | 1052 // The socket being handed out is no longer considered idle, but was |
| 1050 // considered idle until just before this method was called. | 1053 // considered idle until just before this method was called. |
| 1051 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.Socket.NumIdleSockets", | 1054 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.Socket.NumIdleSockets", |
| 1052 idle_socket_count() + 1, 1, 256, 50); | 1055 idle_socket_count() + 1, 1, 256, 50); |
| 1053 } | 1056 } |
| 1054 | 1057 |
| 1055 net_log.AddEvent( | 1058 net_log.AddEvent( |
| 1056 NetLogEventType::SOCKET_POOL_BOUND_TO_SOCKET, | 1059 NetLogEventType::SOCKET_POOL_BOUND_TO_SOCKET, |
| 1057 handle->socket()->NetLog().source().ToEventParametersCallback()); | 1060 handle->socket()->NetLog().source().ToEventParametersCallback()); |
| 1058 | 1061 |
| 1059 handed_out_socket_count_++; | 1062 handed_out_socket_count_++; |
| 1060 group->IncrementActiveSocketCount(); | 1063 group->IncrementActiveSocketCount(); |
| 1061 } | 1064 } |
| 1062 | 1065 |
| 1063 void ClientSocketPoolBaseHelper::AddIdleSocket( | 1066 void ClientSocketPoolBaseHelper::AddIdleSocket( |
| 1064 std::unique_ptr<StreamSocket> socket, | 1067 std::unique_ptr<StreamSocket> socket, |
| 1065 Group* group) { | 1068 Group* group, |
| 1069 const LoadTimingInfo::ConnectTiming& connect_timing) { |
| 1066 DCHECK(socket); | 1070 DCHECK(socket); |
| 1067 IdleSocket idle_socket; | 1071 IdleSocket idle_socket; |
| 1068 idle_socket.socket = socket.release(); | 1072 idle_socket.socket = socket.release(); |
| 1069 idle_socket.start_time = base::TimeTicks::Now(); | 1073 idle_socket.start_time = base::TimeTicks::Now(); |
| 1074 idle_socket.connect_timing = connect_timing; |
| 1070 | 1075 |
| 1071 group->mutable_idle_sockets()->push_back(idle_socket); | 1076 group->mutable_idle_sockets()->push_back(idle_socket); |
| 1072 IncrementIdleCount(); | 1077 IncrementIdleCount(); |
| 1073 } | 1078 } |
| 1074 | 1079 |
| 1075 void ClientSocketPoolBaseHelper::CancelAllConnectJobs() { | 1080 void ClientSocketPoolBaseHelper::CancelAllConnectJobs() { |
| 1076 for (GroupMap::iterator i = group_map_.begin(); i != group_map_.end();) { | 1081 for (GroupMap::iterator i = group_map_.begin(); i != group_map_.end();) { |
| 1077 Group* group = i->second; | 1082 Group* group = i->second; |
| 1078 connecting_socket_count_ -= group->jobs().size(); | 1083 connecting_socket_count_ -= group->jobs().size(); |
| 1079 group->RemoveAllJobs(); | 1084 group->RemoveAllJobs(); |
| (...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1384 // If there are no more requests, kill the backup timer. | 1389 // If there are no more requests, kill the backup timer. |
| 1385 if (pending_requests_.empty()) | 1390 if (pending_requests_.empty()) |
| 1386 backup_job_timer_.Stop(); | 1391 backup_job_timer_.Stop(); |
| 1387 request->CrashIfInvalid(); | 1392 request->CrashIfInvalid(); |
| 1388 return request; | 1393 return request; |
| 1389 } | 1394 } |
| 1390 | 1395 |
| 1391 } // namespace internal | 1396 } // namespace internal |
| 1392 | 1397 |
| 1393 } // namespace net | 1398 } // namespace net |
| OLD | NEW |