| 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/stats_counters.h" | 10 #include "base/stats_counters.h" |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 51 net_log_.AddEvent(NetLog::TYPE_CANCELLED); | 51 net_log_.AddEvent(NetLog::TYPE_CANCELLED); |
| 52 net_log_.EndEvent(NetLog::TYPE_SOCKET_POOL_CONNECT_JOB); | 52 net_log_.EndEvent(NetLog::TYPE_SOCKET_POOL_CONNECT_JOB); |
| 53 } | 53 } |
| 54 } | 54 } |
| 55 | 55 |
| 56 int ConnectJob::Connect() { | 56 int ConnectJob::Connect() { |
| 57 if (timeout_duration_ != base::TimeDelta()) | 57 if (timeout_duration_ != base::TimeDelta()) |
| 58 timer_.Start(timeout_duration_, this, &ConnectJob::OnTimeout); | 58 timer_.Start(timeout_duration_, this, &ConnectJob::OnTimeout); |
| 59 | 59 |
| 60 net_log_.BeginEventWithString(NetLog::TYPE_SOCKET_POOL_CONNECT_JOB, | 60 net_log_.BeginEventWithString(NetLog::TYPE_SOCKET_POOL_CONNECT_JOB, |
| 61 group_name_); | 61 "group_name", group_name_); |
| 62 idle_ = false; | 62 idle_ = false; |
| 63 | 63 |
| 64 int rv = ConnectInternal(); | 64 int rv = ConnectInternal(); |
| 65 | 65 |
| 66 if (rv != ERR_IO_PENDING) { | 66 if (rv != ERR_IO_PENDING) { |
| 67 delegate_ = NULL; | 67 delegate_ = NULL; |
| 68 net_log_.EndEvent(NetLog::TYPE_SOCKET_POOL_CONNECT_JOB); | 68 net_log_.EndEvent(NetLog::TYPE_SOCKET_POOL_CONNECT_JOB); |
| 69 } | 69 } |
| 70 | 70 |
| 71 return rv; | 71 return rv; |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 195 // Can we make another active socket now? | 195 // Can we make another active socket now? |
| 196 if (ReachedMaxSocketsLimit() || | 196 if (ReachedMaxSocketsLimit() || |
| 197 !group.HasAvailableSocketSlot(max_sockets_per_group_)) { | 197 !group.HasAvailableSocketSlot(max_sockets_per_group_)) { |
| 198 if (ReachedMaxSocketsLimit()) { | 198 if (ReachedMaxSocketsLimit()) { |
| 199 // We could check if we really have a stalled group here, but it requires | 199 // We could check if we really have a stalled group here, but it requires |
| 200 // a scan of all groups, so just flip a flag here, and do the check later. | 200 // a scan of all groups, so just flip a flag here, and do the check later. |
| 201 may_have_stalled_group_ = true; | 201 may_have_stalled_group_ = true; |
| 202 | 202 |
| 203 request->net_log().AddEvent(NetLog::TYPE_SOCKET_POOL_STALLED_MAX_SOCKETS); | 203 request->net_log().AddEvent(NetLog::TYPE_SOCKET_POOL_STALLED_MAX_SOCKETS); |
| 204 } else { | 204 } else { |
| 205 request->net_log().AddEvent(NetLog::TYPE_SOCKET_POOL_STALLED_MAX_SOCKETS_P
ER_GROUP); | 205 request->net_log().AddEvent( |
| 206 NetLog::TYPE_SOCKET_POOL_STALLED_MAX_SOCKETS_PER_GROUP); |
| 206 } | 207 } |
| 207 return ERR_IO_PENDING; | 208 return ERR_IO_PENDING; |
| 208 } | 209 } |
| 209 | 210 |
| 210 // Try to reuse a socket. | 211 // Try to reuse a socket. |
| 211 while (!group.idle_sockets.empty()) { | 212 while (!group.idle_sockets.empty()) { |
| 212 IdleSocket idle_socket = group.idle_sockets.back(); | 213 IdleSocket idle_socket = group.idle_sockets.back(); |
| 213 group.idle_sockets.pop_back(); | 214 group.idle_sockets.pop_back(); |
| 214 DecrementIdleCount(); | 215 DecrementIdleCount(); |
| 215 if (idle_socket.socket->IsConnectedAndIdle()) { | 216 if (idle_socket.socket->IsConnectedAndIdle()) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 227 // See if we already have enough connect jobs or sockets that will be released | 228 // See if we already have enough connect jobs or sockets that will be released |
| 228 // soon. | 229 // soon. |
| 229 if (group.HasReleasingSockets()) { | 230 if (group.HasReleasingSockets()) { |
| 230 return ERR_IO_PENDING; | 231 return ERR_IO_PENDING; |
| 231 } | 232 } |
| 232 | 233 |
| 233 // We couldn't find a socket to reuse, so allocate and connect a new one. | 234 // We couldn't find a socket to reuse, so allocate and connect a new one. |
| 234 BoundNetLog job_net_log = BoundNetLog::Make( | 235 BoundNetLog job_net_log = BoundNetLog::Make( |
| 235 request->net_log().net_log(), NetLog::SOURCE_CONNECT_JOB); | 236 request->net_log().net_log(), NetLog::SOURCE_CONNECT_JOB); |
| 236 request->net_log().BeginEventWithInteger( | 237 request->net_log().BeginEventWithInteger( |
| 237 NetLog::TYPE_SOCKET_POOL_CONNECT_JOB_ID, job_net_log.source().id); | 238 NetLog::TYPE_SOCKET_POOL_CONNECT_JOB_ID, |
| 239 "source_id", job_net_log.source().id); |
| 238 | 240 |
| 239 scoped_ptr<ConnectJob> connect_job( | 241 scoped_ptr<ConnectJob> connect_job( |
| 240 connect_job_factory_->NewConnectJob(group_name, *request, this, | 242 connect_job_factory_->NewConnectJob(group_name, *request, this, |
| 241 job_net_log)); | 243 job_net_log)); |
| 242 | 244 |
| 243 int rv = connect_job->Connect(); | 245 int rv = connect_job->Connect(); |
| 244 if (rv == OK) { | 246 if (rv == OK) { |
| 245 request->net_log().EndEventWithInteger( | 247 request->net_log().EndEventWithInteger( |
| 246 NetLog::TYPE_SOCKET_POOL_CONNECT_JOB_ID, job_net_log.source().id); | 248 NetLog::TYPE_SOCKET_POOL_CONNECT_JOB_ID, |
| 249 "source_id", job_net_log.source().id); |
| 247 HandOutSocket(connect_job->ReleaseSocket(), false /* not reused */, | 250 HandOutSocket(connect_job->ReleaseSocket(), false /* not reused */, |
| 248 handle, base::TimeDelta(), &group, request->net_log()); | 251 handle, base::TimeDelta(), &group, request->net_log()); |
| 249 } else if (rv == ERR_IO_PENDING) { | 252 } else if (rv == ERR_IO_PENDING) { |
| 250 // If we don't have any sockets in this group, set a timer for potentially | 253 // If we don't have any sockets in this group, set a timer for potentially |
| 251 // creating a new one. If the SYN is lost, this backup socket may complete | 254 // creating a new one. If the SYN is lost, this backup socket may complete |
| 252 // before the slow socket, improving end user latency. | 255 // before the slow socket, improving end user latency. |
| 253 if (group.IsEmpty() && !group.backup_job && backup_jobs_enabled_) { | 256 if (group.IsEmpty() && !group.backup_job && backup_jobs_enabled_) { |
| 254 group.backup_job = connect_job_factory_->NewConnectJob(group_name, | 257 group.backup_job = connect_job_factory_->NewConnectJob(group_name, |
| 255 *request, | 258 *request, |
| 256 this, | 259 this, |
| 257 job_net_log); | 260 job_net_log); |
| 258 StartBackupSocketTimer(group_name); | 261 StartBackupSocketTimer(group_name); |
| 259 } | 262 } |
| 260 | 263 |
| 261 connecting_socket_count_++; | 264 connecting_socket_count_++; |
| 262 | 265 |
| 263 ConnectJob* job = connect_job.release(); | 266 ConnectJob* job = connect_job.release(); |
| 264 group.jobs.insert(job); | 267 group.jobs.insert(job); |
| 265 } else { | 268 } else { |
| 266 request->net_log().EndEventWithInteger( | 269 request->net_log().EndEventWithInteger( |
| 267 NetLog::TYPE_SOCKET_POOL_CONNECT_JOB_ID, job_net_log.source().id); | 270 NetLog::TYPE_SOCKET_POOL_CONNECT_JOB_ID, |
| 271 "source_id", job_net_log.source().id); |
| 268 if (group.IsEmpty()) | 272 if (group.IsEmpty()) |
| 269 group_map_.erase(group_name); | 273 group_map_.erase(group_name); |
| 270 } | 274 } |
| 271 | 275 |
| 272 return rv; | 276 return rv; |
| 273 } | 277 } |
| 274 | 278 |
| 275 void ClientSocketPoolBaseHelper::StartBackupSocketTimer( | 279 void ClientSocketPoolBaseHelper::StartBackupSocketTimer( |
| 276 const std::string& group_name) { | 280 const std::string& group_name) { |
| 277 CHECK(ContainsKey(group_map_, group_name)); | 281 CHECK(ContainsKey(group_map_, group_name)); |
| (...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 562 | 566 |
| 563 BoundNetLog job_log = job->net_log(); | 567 BoundNetLog job_log = job->net_log(); |
| 564 RemoveConnectJob(job, &group); | 568 RemoveConnectJob(job, &group); |
| 565 | 569 |
| 566 if (result == OK) { | 570 if (result == OK) { |
| 567 DCHECK(socket.get()); | 571 DCHECK(socket.get()); |
| 568 if (!group.pending_requests.empty()) { | 572 if (!group.pending_requests.empty()) { |
| 569 scoped_ptr<const Request> r(RemoveRequestFromQueue( | 573 scoped_ptr<const Request> r(RemoveRequestFromQueue( |
| 570 group.pending_requests.begin(), &group.pending_requests)); | 574 group.pending_requests.begin(), &group.pending_requests)); |
| 571 r->net_log().EndEventWithInteger(NetLog::TYPE_SOCKET_POOL_CONNECT_JOB_ID, | 575 r->net_log().EndEventWithInteger(NetLog::TYPE_SOCKET_POOL_CONNECT_JOB_ID, |
| 572 job_log.source().id); | 576 "source_id", job_log.source().id); |
| 573 r->net_log().EndEvent(NetLog::TYPE_SOCKET_POOL); | 577 r->net_log().EndEvent(NetLog::TYPE_SOCKET_POOL); |
| 574 HandOutSocket( | 578 HandOutSocket( |
| 575 socket.release(), false /* unused socket */, r->handle(), | 579 socket.release(), false /* unused socket */, r->handle(), |
| 576 base::TimeDelta(), &group, r->net_log()); | 580 base::TimeDelta(), &group, r->net_log()); |
| 577 r->callback()->Run(result); | 581 r->callback()->Run(result); |
| 578 } else { | 582 } else { |
| 579 AddIdleSocket(socket.release(), false /* unused socket */, &group); | 583 AddIdleSocket(socket.release(), false /* unused socket */, &group); |
| 580 OnAvailableSocketSlot(group_name, &group); | 584 OnAvailableSocketSlot(group_name, &group); |
| 581 } | 585 } |
| 582 } else { | 586 } else { |
| 583 DCHECK(!socket.get()); | 587 DCHECK(!socket.get()); |
| 584 if (!group.pending_requests.empty()) { | 588 if (!group.pending_requests.empty()) { |
| 585 scoped_ptr<const Request> r(RemoveRequestFromQueue( | 589 scoped_ptr<const Request> r(RemoveRequestFromQueue( |
| 586 group.pending_requests.begin(), &group.pending_requests)); | 590 group.pending_requests.begin(), &group.pending_requests)); |
| 587 r->net_log().EndEventWithInteger(NetLog::TYPE_SOCKET_POOL_CONNECT_JOB_ID, | 591 r->net_log().EndEventWithInteger(NetLog::TYPE_SOCKET_POOL_CONNECT_JOB_ID, |
| 588 job_log.source().id); | 592 "source_id", job_log.source().id); |
| 589 r->net_log().EndEvent(NetLog::TYPE_SOCKET_POOL); | 593 r->net_log().EndEvent(NetLog::TYPE_SOCKET_POOL); |
| 590 r->callback()->Run(result); | 594 r->callback()->Run(result); |
| 591 } | 595 } |
| 592 MaybeOnAvailableSocketSlot(group_name); | 596 MaybeOnAvailableSocketSlot(group_name); |
| 593 } | 597 } |
| 594 } | 598 } |
| 595 | 599 |
| 596 void ClientSocketPoolBaseHelper::OnIPAddressChanged() { | 600 void ClientSocketPoolBaseHelper::OnIPAddressChanged() { |
| 597 CloseIdleSockets(); | 601 CloseIdleSockets(); |
| 598 } | 602 } |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 666 bool reused, | 670 bool reused, |
| 667 ClientSocketHandle* handle, | 671 ClientSocketHandle* handle, |
| 668 base::TimeDelta idle_time, | 672 base::TimeDelta idle_time, |
| 669 Group* group, | 673 Group* group, |
| 670 const BoundNetLog& net_log) { | 674 const BoundNetLog& net_log) { |
| 671 DCHECK(socket); | 675 DCHECK(socket); |
| 672 handle->set_socket(socket); | 676 handle->set_socket(socket); |
| 673 handle->set_is_reused(reused); | 677 handle->set_is_reused(reused); |
| 674 handle->set_idle_time(idle_time); | 678 handle->set_idle_time(idle_time); |
| 675 | 679 |
| 676 if (reused) | 680 if (reused) { |
| 677 net_log.AddStringLiteral("Reusing socket."); | 681 net_log.AddEventWithInteger( |
| 678 if (idle_time != base::TimeDelta()) { | 682 NetLog::TYPE_SOCKET_POOL_REUSED_AN_EXISTING_SOCKET, |
| 679 net_log.AddString( | 683 "idle_ms", static_cast<int>(idle_time.InMilliseconds())); |
| 680 StringPrintf("Socket sat idle for %" PRId64 " milliseconds", | |
| 681 idle_time.InMilliseconds())); | |
| 682 } | 684 } |
| 685 |
| 683 net_log.AddEventWithInteger(NetLog::TYPE_SOCKET_POOL_SOCKET_ID, | 686 net_log.AddEventWithInteger(NetLog::TYPE_SOCKET_POOL_SOCKET_ID, |
| 684 socket->NetLog().source().id); | 687 "source_id", socket->NetLog().source().id); |
| 685 | 688 |
| 686 handed_out_socket_count_++; | 689 handed_out_socket_count_++; |
| 687 group->active_socket_count++; | 690 group->active_socket_count++; |
| 688 } | 691 } |
| 689 | 692 |
| 690 void ClientSocketPoolBaseHelper::AddIdleSocket( | 693 void ClientSocketPoolBaseHelper::AddIdleSocket( |
| 691 ClientSocket* socket, bool used, Group* group) { | 694 ClientSocket* socket, bool used, Group* group) { |
| 692 DCHECK(socket); | 695 DCHECK(socket); |
| 693 IdleSocket idle_socket; | 696 IdleSocket idle_socket; |
| 694 idle_socket.socket = socket; | 697 idle_socket.socket = socket; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 722 bool ClientSocketPoolBaseHelper::ReachedMaxSocketsLimit() const { | 725 bool ClientSocketPoolBaseHelper::ReachedMaxSocketsLimit() const { |
| 723 // Each connecting socket will eventually connect and be handed out. | 726 // Each connecting socket will eventually connect and be handed out. |
| 724 int total = handed_out_socket_count_ + connecting_socket_count_; | 727 int total = handed_out_socket_count_ + connecting_socket_count_; |
| 725 DCHECK_LE(total, max_sockets_); | 728 DCHECK_LE(total, max_sockets_); |
| 726 return total == max_sockets_; | 729 return total == max_sockets_; |
| 727 } | 730 } |
| 728 | 731 |
| 729 } // namespace internal | 732 } // namespace internal |
| 730 | 733 |
| 731 } // namespace net | 734 } // namespace net |
| OLD | NEW |