Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(133)

Side by Side Diff: net/socket/client_socket_pool_base.cc

Issue 2077004: Reland my close on idle socket change. (Closed) Base URL: http://src.chromium.org/git/chromium.git
Patch Set: Merge Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/socket/client_socket_pool_base.h ('k') | net/socket/client_socket_pool_base_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 int ClientSocketPoolBaseHelper::RequestSocketInternal( 180 int ClientSocketPoolBaseHelper::RequestSocketInternal(
181 const std::string& group_name, 181 const std::string& group_name,
182 const Request* request) { 182 const Request* request) {
183 DCHECK_GE(request->priority(), 0); 183 DCHECK_GE(request->priority(), 0);
184 CompletionCallback* const callback = request->callback(); 184 CompletionCallback* const callback = request->callback();
185 CHECK(callback); 185 CHECK(callback);
186 ClientSocketHandle* const handle = request->handle(); 186 ClientSocketHandle* const handle = request->handle();
187 CHECK(handle); 187 CHECK(handle);
188 Group& group = group_map_[group_name]; 188 Group& group = group_map_[group_name];
189 189
190 // Can we make another active socket now?
191 if (ReachedMaxSocketsLimit() ||
192 !group.HasAvailableSocketSlot(max_sockets_per_group_)) {
193 if (ReachedMaxSocketsLimit()) {
194 // We could check if we really have a stalled group here, but it requires
195 // a scan of all groups, so just flip a flag here, and do the check later.
196 may_have_stalled_group_ = true;
197
198 request->net_log().AddEvent(NetLog::TYPE_SOCKET_POOL_STALLED_MAX_SOCKETS,
199 NULL);
200 } else {
201 request->net_log().AddEvent(
202 NetLog::TYPE_SOCKET_POOL_STALLED_MAX_SOCKETS_PER_GROUP, NULL);
203 }
204 return ERR_IO_PENDING;
205 }
206
207 // Try to reuse a socket. 190 // Try to reuse a socket.
208 while (!group.idle_sockets.empty()) { 191 while (!group.idle_sockets.empty()) {
209 IdleSocket idle_socket = group.idle_sockets.back(); 192 IdleSocket idle_socket = group.idle_sockets.back();
210 group.idle_sockets.pop_back(); 193 group.idle_sockets.pop_back();
211 DecrementIdleCount(); 194 DecrementIdleCount();
212 if (idle_socket.socket->IsConnectedAndIdle()) { 195 if (idle_socket.socket->IsConnectedAndIdle()) {
213 // We found one we can reuse! 196 // We found one we can reuse!
214 base::TimeDelta idle_time = 197 base::TimeDelta idle_time =
215 base::TimeTicks::Now() - idle_socket.start_time; 198 base::TimeTicks::Now() - idle_socket.start_time;
216 HandOutSocket( 199 HandOutSocket(
217 idle_socket.socket, idle_socket.used, handle, idle_time, &group, 200 idle_socket.socket, idle_socket.used, handle, idle_time, &group,
218 request->net_log()); 201 request->net_log());
219 return OK; 202 return OK;
220 } 203 }
221 delete idle_socket.socket; 204 delete idle_socket.socket;
222 } 205 }
223 206
207 // Can we make another active socket now?
208 if (!group.HasAvailableSocketSlot(max_sockets_per_group_)) {
209 request->net_log().AddEvent(
210 NetLog::TYPE_SOCKET_POOL_STALLED_MAX_SOCKETS_PER_GROUP, NULL);
211 return ERR_IO_PENDING;
212 }
213
214 if (ReachedMaxSocketsLimit()) {
215 if (idle_socket_count() > 0) {
216 CloseOneIdleSocket();
217 } else {
218 // We could check if we really have a stalled group here, but it requires
219 // a scan of all groups, so just flip a flag here, and do the check later.
220 may_have_stalled_group_ = true;
221 request->net_log().AddEvent(
222 NetLog::TYPE_SOCKET_POOL_STALLED_MAX_SOCKETS, NULL);
223 return ERR_IO_PENDING;
224 }
225 }
226
224 // See if we already have enough connect jobs or sockets that will be released 227 // See if we already have enough connect jobs or sockets that will be released
225 // soon. 228 // soon.
226 if (group.HasReleasingSockets()) { 229 if (group.HasReleasingSockets()) {
227 return ERR_IO_PENDING; 230 return ERR_IO_PENDING;
228 } 231 }
229 232
230 // We couldn't find a socket to reuse, so allocate and connect a new one. 233 // We couldn't find a socket to reuse, so allocate and connect a new one.
231 BoundNetLog job_net_log = BoundNetLog::Make( 234 BoundNetLog job_net_log = BoundNetLog::Make(
232 request->net_log().net_log(), NetLog::SOURCE_CONNECT_JOB); 235 request->net_log().net_log(), NetLog::SOURCE_CONNECT_JOB);
233 request->net_log().BeginEvent( 236 request->net_log().BeginEvent(
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after
495 // sure it doesn't get ridiculously high. 498 // sure it doesn't get ridiculously high.
496 499
497 int iterations = 0; 500 int iterations = 0;
498 while (num_releasing_sockets_ == 0) { 501 while (num_releasing_sockets_ == 0) {
499 CHECK_LT(iterations, 1000) << "Probably stuck in an infinite loop."; 502 CHECK_LT(iterations, 1000) << "Probably stuck in an infinite loop.";
500 std::string top_group_name; 503 std::string top_group_name;
501 Group* top_group = NULL; 504 Group* top_group = NULL;
502 int stalled_group_count = FindTopStalledGroup(&top_group, &top_group_name); 505 int stalled_group_count = FindTopStalledGroup(&top_group, &top_group_name);
503 if (stalled_group_count >= 1) { 506 if (stalled_group_count >= 1) {
504 if (ReachedMaxSocketsLimit()) { 507 if (ReachedMaxSocketsLimit()) {
505 // We can't activate more sockets since we're already at our global 508 if (idle_socket_count() > 0) {
506 // limit. 509 CloseOneIdleSocket();
507 may_have_stalled_group_ = true; 510 } else {
508 return; 511 // We can't activate more sockets since we're already at our global
512 // limit.
513 may_have_stalled_group_ = true;
514 return;
515 }
509 } 516 }
510 517
511 ProcessPendingRequest(top_group_name, top_group); 518 ProcessPendingRequest(top_group_name, top_group);
512 } else { 519 } else {
513 may_have_stalled_group_ = false; 520 may_have_stalled_group_ = false;
514 return; 521 return;
515 } 522 }
516 523
517 iterations++; 524 iterations++;
518 } 525 }
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
629 void ClientSocketPoolBaseHelper::OnAvailableSocketSlot( 636 void ClientSocketPoolBaseHelper::OnAvailableSocketSlot(
630 const std::string& group_name, Group* group) { 637 const std::string& group_name, Group* group) {
631 if (may_have_stalled_group_) { 638 if (may_have_stalled_group_) {
632 std::string top_group_name; 639 std::string top_group_name;
633 Group* top_group = NULL; 640 Group* top_group = NULL;
634 int stalled_group_count = FindTopStalledGroup(&top_group, &top_group_name); 641 int stalled_group_count = FindTopStalledGroup(&top_group, &top_group_name);
635 if (stalled_group_count == 0 || 642 if (stalled_group_count == 0 ||
636 (stalled_group_count == 1 && top_group->num_releasing_sockets == 0)) { 643 (stalled_group_count == 1 && top_group->num_releasing_sockets == 0)) {
637 may_have_stalled_group_ = false; 644 may_have_stalled_group_ = false;
638 } 645 }
639 if (stalled_group_count >= 1) 646 if (stalled_group_count >= 1) {
647 CHECK_GE(1, idle_socket_count());
640 ProcessPendingRequest(top_group_name, top_group); 648 ProcessPendingRequest(top_group_name, top_group);
649 }
641 } else if (!group->pending_requests.empty()) { 650 } else if (!group->pending_requests.empty()) {
642 ProcessPendingRequest(group_name, group); 651 ProcessPendingRequest(group_name, group);
643 // |group| may no longer be valid after this point. Be careful not to 652 // |group| may no longer be valid after this point. Be careful not to
644 // access it again. 653 // access it again.
645 } else if (group->IsEmpty()) { 654 } else if (group->IsEmpty()) {
646 // Delete |group| if no longer needed. |group| will no longer be valid. 655 // Delete |group| if no longer needed. |group| will no longer be valid.
647 group_map_.erase(group_name); 656 group_map_.erase(group_name);
648 } 657 }
649 } 658 }
650 659
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
719 if (group.IsEmpty()) { 728 if (group.IsEmpty()) {
720 group_map_.erase(i++); 729 group_map_.erase(i++);
721 } else { 730 } else {
722 ++i; 731 ++i;
723 } 732 }
724 } 733 }
725 } 734 }
726 735
727 bool ClientSocketPoolBaseHelper::ReachedMaxSocketsLimit() const { 736 bool ClientSocketPoolBaseHelper::ReachedMaxSocketsLimit() const {
728 // Each connecting socket will eventually connect and be handed out. 737 // Each connecting socket will eventually connect and be handed out.
729 int total = handed_out_socket_count_ + connecting_socket_count_; 738 int total = handed_out_socket_count_ + connecting_socket_count_ +
739 idle_socket_count();
730 DCHECK_LE(total, max_sockets_); 740 DCHECK_LE(total, max_sockets_);
731 if (total < max_sockets_) 741 if (total < max_sockets_)
732 return false; 742 return false;
733 LOG(WARNING) << "ReachedMaxSocketsLimit: " << total << "/" << max_sockets_; 743 LOG(WARNING) << "ReachedMaxSocketsLimit: " << total << "/" << max_sockets_;
734 return true; 744 return true;
735 } 745 }
736 746
747 void ClientSocketPoolBaseHelper::CloseOneIdleSocket() {
748 CHECK_GT(idle_socket_count(), 0);
749
750 for (GroupMap::iterator i = group_map_.begin(); i != group_map_.end(); ++i) {
751 Group& group = i->second;
752
753 if (!group.idle_sockets.empty()) {
754 std::deque<IdleSocket>::iterator j = group.idle_sockets.begin();
755 delete j->socket;
756 group.idle_sockets.erase(j);
757 DecrementIdleCount();
758 if (group.IsEmpty())
759 group_map_.erase(i);
760
761 return;
762 }
763 }
764
765 LOG(DFATAL) << "No idle socket found to close!.";
766 }
767
737 } // namespace internal 768 } // namespace internal
738 769
739 } // namespace net 770 } // namespace net
OLDNEW
« no previous file with comments | « net/socket/client_socket_pool_base.h ('k') | net/socket/client_socket_pool_base_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698