| 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 |