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 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
135 handed_out_socket_count_(0), | 135 handed_out_socket_count_(0), |
136 num_releasing_sockets_(0), | 136 num_releasing_sockets_(0), |
137 max_sockets_(max_sockets), | 137 max_sockets_(max_sockets), |
138 max_sockets_per_group_(max_sockets_per_group), | 138 max_sockets_per_group_(max_sockets_per_group), |
139 unused_idle_socket_timeout_(unused_idle_socket_timeout), | 139 unused_idle_socket_timeout_(unused_idle_socket_timeout), |
140 used_idle_socket_timeout_(used_idle_socket_timeout), | 140 used_idle_socket_timeout_(used_idle_socket_timeout), |
141 may_have_stalled_group_(false), | 141 may_have_stalled_group_(false), |
142 connect_job_factory_(connect_job_factory), | 142 connect_job_factory_(connect_job_factory), |
143 network_change_notifier_(network_change_notifier), | 143 network_change_notifier_(network_change_notifier), |
144 backup_jobs_enabled_(false), | 144 backup_jobs_enabled_(false), |
145 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { | 145 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)), |
| 146 pool_generation_number_(0) { |
146 DCHECK_LE(0, max_sockets_per_group); | 147 DCHECK_LE(0, max_sockets_per_group); |
147 DCHECK_LE(max_sockets_per_group, max_sockets); | 148 DCHECK_LE(max_sockets_per_group, max_sockets); |
148 | 149 |
149 if (network_change_notifier_) | 150 if (network_change_notifier_) |
150 network_change_notifier_->AddObserver(this); | 151 network_change_notifier_->AddObserver(this); |
151 } | 152 } |
152 | 153 |
153 ClientSocketPoolBaseHelper::~ClientSocketPoolBaseHelper() { | 154 ClientSocketPoolBaseHelper::~ClientSocketPoolBaseHelper() { |
154 CancelAllConnectJobs(); | 155 CancelAllConnectJobs(); |
155 | 156 |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
363 // TODO(willchan): Cancel the job in the earliest LoadState. | 364 // TODO(willchan): Cancel the job in the earliest LoadState. |
364 RemoveConnectJob(*group.jobs.begin(), &group); | 365 RemoveConnectJob(*group.jobs.begin(), &group); |
365 OnAvailableSocketSlot(group_name, &group); | 366 OnAvailableSocketSlot(group_name, &group); |
366 } | 367 } |
367 return; | 368 return; |
368 } | 369 } |
369 } | 370 } |
370 } | 371 } |
371 | 372 |
372 void ClientSocketPoolBaseHelper::ReleaseSocket(const std::string& group_name, | 373 void ClientSocketPoolBaseHelper::ReleaseSocket(const std::string& group_name, |
373 ClientSocket* socket) { | 374 ClientSocket* socket, |
| 375 int id) { |
374 Group& group = group_map_[group_name]; | 376 Group& group = group_map_[group_name]; |
375 group.num_releasing_sockets++; | 377 group.num_releasing_sockets++; |
376 num_releasing_sockets_++; | 378 num_releasing_sockets_++; |
377 DCHECK_LE(group.num_releasing_sockets, group.active_socket_count); | 379 DCHECK_LE(group.num_releasing_sockets, group.active_socket_count); |
378 // Run this asynchronously to allow the caller to finish before we let | 380 // Run this asynchronously to allow the caller to finish before we let |
379 // another to begin doing work. This also avoids nasty recursion issues. | 381 // another to begin doing work. This also avoids nasty recursion issues. |
380 // NOTE: We cannot refer to the handle argument after this method returns. | 382 // NOTE: We cannot refer to the handle argument after this method returns. |
381 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( | 383 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( |
382 this, &ClientSocketPoolBaseHelper::DoReleaseSocket, group_name, socket)); | 384 this, &ClientSocketPoolBaseHelper::DoReleaseSocket, group_name, socket, id
)); |
383 } | 385 } |
384 | 386 |
385 void ClientSocketPoolBaseHelper::CloseIdleSockets() { | 387 void ClientSocketPoolBaseHelper::CloseIdleSockets() { |
386 CleanupIdleSockets(true); | 388 CleanupIdleSockets(true); |
387 } | 389 } |
388 | 390 |
389 int ClientSocketPoolBaseHelper::IdleSocketCountInGroup( | 391 int ClientSocketPoolBaseHelper::IdleSocketCountInGroup( |
390 const std::string& group_name) const { | 392 const std::string& group_name) const { |
391 GroupMap::const_iterator i = group_map_.find(group_name); | 393 GroupMap::const_iterator i = group_map_.find(group_name); |
392 CHECK(i != group_map_.end()); | 394 CHECK(i != group_map_.end()); |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
476 timer_.Start(TimeDelta::FromSeconds(kCleanupInterval), this, | 478 timer_.Start(TimeDelta::FromSeconds(kCleanupInterval), this, |
477 &ClientSocketPoolBaseHelper::OnCleanupTimerFired); | 479 &ClientSocketPoolBaseHelper::OnCleanupTimerFired); |
478 } | 480 } |
479 | 481 |
480 void ClientSocketPoolBaseHelper::DecrementIdleCount() { | 482 void ClientSocketPoolBaseHelper::DecrementIdleCount() { |
481 if (--idle_socket_count_ == 0) | 483 if (--idle_socket_count_ == 0) |
482 timer_.Stop(); | 484 timer_.Stop(); |
483 } | 485 } |
484 | 486 |
485 void ClientSocketPoolBaseHelper::DoReleaseSocket(const std::string& group_name, | 487 void ClientSocketPoolBaseHelper::DoReleaseSocket(const std::string& group_name, |
486 ClientSocket* socket) { | 488 ClientSocket* socket, |
| 489 int id) { |
487 // Running callbacks can cause the last outside reference to be released. | 490 // Running callbacks can cause the last outside reference to be released. |
488 // Hold onto a reference. | 491 // Hold onto a reference. |
489 scoped_refptr<ClientSocketPoolBaseHelper> ref_holder(this); | 492 scoped_refptr<ClientSocketPoolBaseHelper> ref_holder(this); |
490 | 493 |
491 GroupMap::iterator i = group_map_.find(group_name); | 494 GroupMap::iterator i = group_map_.find(group_name); |
492 CHECK(i != group_map_.end()); | 495 CHECK(i != group_map_.end()); |
493 | 496 |
494 Group& group = i->second; | 497 Group& group = i->second; |
495 | 498 |
496 group.num_releasing_sockets--; | 499 group.num_releasing_sockets--; |
497 DCHECK_GE(group.num_releasing_sockets, 0); | 500 DCHECK_GE(group.num_releasing_sockets, 0); |
498 | 501 |
499 CHECK_GT(handed_out_socket_count_, 0); | 502 CHECK_GT(handed_out_socket_count_, 0); |
500 handed_out_socket_count_--; | 503 handed_out_socket_count_--; |
501 | 504 |
502 CHECK_GT(group.active_socket_count, 0); | 505 CHECK_GT(group.active_socket_count, 0); |
503 group.active_socket_count--; | 506 group.active_socket_count--; |
504 | 507 |
505 CHECK_GT(num_releasing_sockets_, 0); | 508 CHECK_GT(num_releasing_sockets_, 0); |
506 num_releasing_sockets_--; | 509 num_releasing_sockets_--; |
507 | 510 |
508 const bool can_reuse = socket->IsConnectedAndIdle(); | 511 const bool can_reuse = socket->IsConnectedAndIdle() && |
| 512 id == pool_generation_number_; |
509 if (can_reuse) { | 513 if (can_reuse) { |
510 AddIdleSocket(socket, true /* used socket */, &group); | 514 AddIdleSocket(socket, true /* used socket */, &group); |
511 } else { | 515 } else { |
512 delete socket; | 516 delete socket; |
513 } | 517 } |
514 | 518 |
515 // If there are no more releasing sockets, then we might have to process | 519 // If there are no more releasing sockets, then we might have to process |
516 // multiple available socket slots, since we stalled their processing until | 520 // multiple available socket slots, since we stalled their processing until |
517 // all sockets have been released. Note that ProcessPendingRequest() will | 521 // all sockets have been released. Note that ProcessPendingRequest() will |
518 // invoke user callbacks, so |num_releasing_sockets_| may change. | 522 // invoke user callbacks, so |num_releasing_sockets_| may change. |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
622 group.pending_requests.begin(), &group.pending_requests)); | 626 group.pending_requests.begin(), &group.pending_requests)); |
623 LogBoundConnectJobToRequest(job_log.source(), r.get()); | 627 LogBoundConnectJobToRequest(job_log.source(), r.get()); |
624 r->net_log().EndEvent(NetLog::TYPE_SOCKET_POOL, | 628 r->net_log().EndEvent(NetLog::TYPE_SOCKET_POOL, |
625 new NetLogIntegerParameter("net_error", result)); | 629 new NetLogIntegerParameter("net_error", result)); |
626 r->callback()->Run(result); | 630 r->callback()->Run(result); |
627 } | 631 } |
628 MaybeOnAvailableSocketSlot(group_name); | 632 MaybeOnAvailableSocketSlot(group_name); |
629 } | 633 } |
630 } | 634 } |
631 | 635 |
632 void ClientSocketPoolBaseHelper::OnIPAddressChanged() { | 636 void ClientSocketPoolBaseHelper::Flush() { |
| 637 pool_generation_number_++; |
633 CancelAllConnectJobs(); | 638 CancelAllConnectJobs(); |
634 CloseIdleSockets(); | 639 CloseIdleSockets(); |
635 } | 640 } |
636 | 641 |
637 void ClientSocketPoolBaseHelper::RemoveConnectJob(const ConnectJob *job, | 642 void ClientSocketPoolBaseHelper::RemoveConnectJob(const ConnectJob *job, |
638 Group* group) { | 643 Group* group) { |
639 CHECK_GT(connecting_socket_count_, 0); | 644 CHECK_GT(connecting_socket_count_, 0); |
640 connecting_socket_count_--; | 645 connecting_socket_count_--; |
641 | 646 |
642 DCHECK(job); | 647 DCHECK(job); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
705 ClientSocket* socket, | 710 ClientSocket* socket, |
706 bool reused, | 711 bool reused, |
707 ClientSocketHandle* handle, | 712 ClientSocketHandle* handle, |
708 base::TimeDelta idle_time, | 713 base::TimeDelta idle_time, |
709 Group* group, | 714 Group* group, |
710 const BoundNetLog& net_log) { | 715 const BoundNetLog& net_log) { |
711 DCHECK(socket); | 716 DCHECK(socket); |
712 handle->set_socket(socket); | 717 handle->set_socket(socket); |
713 handle->set_is_reused(reused); | 718 handle->set_is_reused(reused); |
714 handle->set_idle_time(idle_time); | 719 handle->set_idle_time(idle_time); |
| 720 handle->set_pool_id(pool_generation_number_); |
715 | 721 |
716 if (reused) { | 722 if (reused) { |
717 net_log.AddEvent( | 723 net_log.AddEvent( |
718 NetLog::TYPE_SOCKET_POOL_REUSED_AN_EXISTING_SOCKET, | 724 NetLog::TYPE_SOCKET_POOL_REUSED_AN_EXISTING_SOCKET, |
719 new NetLogIntegerParameter( | 725 new NetLogIntegerParameter( |
720 "idle_ms", static_cast<int>(idle_time.InMilliseconds()))); | 726 "idle_ms", static_cast<int>(idle_time.InMilliseconds()))); |
721 } | 727 } |
722 | 728 |
723 net_log.AddEvent(NetLog::TYPE_SOCKET_POOL_BOUND_TO_SOCKET, | 729 net_log.AddEvent(NetLog::TYPE_SOCKET_POOL_BOUND_TO_SOCKET, |
724 new NetLogSourceParameter( | 730 new NetLogSourceParameter( |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
766 DCHECK_LE(total, max_sockets_); | 772 DCHECK_LE(total, max_sockets_); |
767 if (total < max_sockets_) | 773 if (total < max_sockets_) |
768 return false; | 774 return false; |
769 LOG(WARNING) << "ReachedMaxSocketsLimit: " << total << "/" << max_sockets_; | 775 LOG(WARNING) << "ReachedMaxSocketsLimit: " << total << "/" << max_sockets_; |
770 return true; | 776 return true; |
771 } | 777 } |
772 | 778 |
773 } // namespace internal | 779 } // namespace internal |
774 | 780 |
775 } // namespace net | 781 } // namespace net |
OLD | NEW |