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 |