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

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

Issue 2994003: Refactor how ClientSocketPoolBaseHelper avoids re-entrancy. (Closed) Base URL: http://src.chromium.org/git/chromium.git
Patch Set: Merge. Created 10 years, 5 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 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 : idle_socket_count_(0), 132 : idle_socket_count_(0),
133 connecting_socket_count_(0), 133 connecting_socket_count_(0),
134 handed_out_socket_count_(0), 134 handed_out_socket_count_(0),
135 max_sockets_(max_sockets), 135 max_sockets_(max_sockets),
136 max_sockets_per_group_(max_sockets_per_group), 136 max_sockets_per_group_(max_sockets_per_group),
137 unused_idle_socket_timeout_(unused_idle_socket_timeout), 137 unused_idle_socket_timeout_(unused_idle_socket_timeout),
138 used_idle_socket_timeout_(used_idle_socket_timeout), 138 used_idle_socket_timeout_(used_idle_socket_timeout),
139 connect_job_factory_(connect_job_factory), 139 connect_job_factory_(connect_job_factory),
140 backup_jobs_enabled_(false), 140 backup_jobs_enabled_(false),
141 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)), 141 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)),
142 pool_generation_number_(0), 142 pool_generation_number_(0) {
143 last_stalled_group_count_(0) {
144 DCHECK_LE(0, max_sockets_per_group); 143 DCHECK_LE(0, max_sockets_per_group);
145 DCHECK_LE(max_sockets_per_group, max_sockets); 144 DCHECK_LE(max_sockets_per_group, max_sockets);
146 145
147 NetworkChangeNotifier::AddObserver(this); 146 NetworkChangeNotifier::AddObserver(this);
148 } 147 }
149 148
150 ClientSocketPoolBaseHelper::~ClientSocketPoolBaseHelper() { 149 ClientSocketPoolBaseHelper::~ClientSocketPoolBaseHelper() {
151 CancelAllConnectJobs(); 150 CancelAllConnectJobs();
152 151
153 // Clean up any idle sockets. Assert that we have no remaining active 152 // Clean up any idle sockets. Assert that we have no remaining active
154 // sockets or pending requests. They should have all been cleaned up prior 153 // sockets or pending requests. They should have all been cleaned up prior
155 // to the manager being destroyed. 154 // to the manager being destroyed.
156 CloseIdleSockets(); 155 CloseIdleSockets();
157 CHECK(group_map_.empty()); 156 CHECK(group_map_.empty());
157 DCHECK(pending_callback_map_.empty());
158 DCHECK_EQ(0, connecting_socket_count_); 158 DCHECK_EQ(0, connecting_socket_count_);
159 159
160 NetworkChangeNotifier::RemoveObserver(this); 160 NetworkChangeNotifier::RemoveObserver(this);
161 } 161 }
162 162
163 // InsertRequestIntoQueue inserts the request into the queue based on 163 // InsertRequestIntoQueue inserts the request into the queue based on
164 // priority. Highest priorities are closest to the front. Older requests are 164 // priority. Highest priorities are closest to the front. Older requests are
165 // prioritized over requests of equal priority. 165 // prioritized over requests of equal priority.
166 // 166 //
167 // static 167 // static
(...skipping 16 matching lines...) Expand all
184 184
185 int ClientSocketPoolBaseHelper::RequestSocket( 185 int ClientSocketPoolBaseHelper::RequestSocket(
186 const std::string& group_name, 186 const std::string& group_name,
187 const Request* request) { 187 const Request* request) {
188 request->net_log().BeginEvent(NetLog::TYPE_SOCKET_POOL, NULL); 188 request->net_log().BeginEvent(NetLog::TYPE_SOCKET_POOL, NULL);
189 Group& group = group_map_[group_name]; 189 Group& group = group_map_[group_name];
190 190
191 int rv = RequestSocketInternal(group_name, request); 191 int rv = RequestSocketInternal(group_name, request);
192 if (rv != ERR_IO_PENDING) { 192 if (rv != ERR_IO_PENDING) {
193 request->net_log().EndEvent(NetLog::TYPE_SOCKET_POOL, NULL); 193 request->net_log().EndEvent(NetLog::TYPE_SOCKET_POOL, NULL);
194 CHECK(!request->handle()->is_initialized());
194 delete request; 195 delete request;
195 } else { 196 } else {
196 InsertRequestIntoQueue(request, &group.pending_requests); 197 InsertRequestIntoQueue(request, &group.pending_requests);
197 } 198 }
198 return rv; 199 return rv;
199 } 200 }
200 201
201 int ClientSocketPoolBaseHelper::RequestSocketInternal( 202 int ClientSocketPoolBaseHelper::RequestSocketInternal(
202 const std::string& group_name, 203 const std::string& group_name,
203 const Request* request) { 204 const Request* request) {
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
255 256
256 ConnectJob* job = connect_job.release(); 257 ConnectJob* job = connect_job.release();
257 group.jobs.insert(job); 258 group.jobs.insert(job);
258 } else { 259 } else {
259 LogBoundConnectJobToRequest(connect_job->net_log().source(), request); 260 LogBoundConnectJobToRequest(connect_job->net_log().source(), request);
260 connect_job->GetAdditionalErrorState(handle); 261 connect_job->GetAdditionalErrorState(handle);
261 ClientSocket* error_socket = connect_job->ReleaseSocket(); 262 ClientSocket* error_socket = connect_job->ReleaseSocket();
262 if (error_socket) { 263 if (error_socket) {
263 HandOutSocket(error_socket, false /* not reused */, handle, 264 HandOutSocket(error_socket, false /* not reused */, handle,
264 base::TimeDelta(), &group, request->net_log()); 265 base::TimeDelta(), &group, request->net_log());
266 } else if (group.IsEmpty()) {
267 group_map_.erase(group_name);
265 } 268 }
266 if (group.IsEmpty())
267 group_map_.erase(group_name);
268 } 269 }
269 270
270 return rv; 271 return rv;
271 } 272 }
272 273
273 bool ClientSocketPoolBaseHelper::AssignIdleSocketToGroup(Group* group, 274 bool ClientSocketPoolBaseHelper::AssignIdleSocketToGroup(
274 const Request* request) { 275 Group* group, const Request* request) {
275 // Iterate through the list of idle sockets until we find one or exhaust 276 // Iterate through the list of idle sockets until we find one or exhaust
276 // the list. 277 // the list.
277 while (!group->idle_sockets.empty()) { 278 while (!group->idle_sockets.empty()) {
278 IdleSocket idle_socket = group->idle_sockets.back(); 279 IdleSocket idle_socket = group->idle_sockets.back();
279 group->idle_sockets.pop_back(); 280 group->idle_sockets.pop_back();
280 DecrementIdleCount(); 281 DecrementIdleCount();
281 if (idle_socket.socket->IsConnectedAndIdle()) { 282 if (idle_socket.socket->IsConnectedAndIdle()) {
282 // We found one we can reuse! 283 // We found one we can reuse!
283 base::TimeDelta idle_time = 284 base::TimeDelta idle_time =
284 base::TimeTicks::Now() - idle_socket.start_time; 285 base::TimeTicks::Now() - idle_socket.start_time;
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
348 int rv = group.backup_job->Connect(); 349 int rv = group.backup_job->Connect();
349 connecting_socket_count_++; 350 connecting_socket_count_++;
350 group.jobs.insert(group.backup_job); 351 group.jobs.insert(group.backup_job);
351 ConnectJob* job = group.backup_job; 352 ConnectJob* job = group.backup_job;
352 group.backup_job = NULL; 353 group.backup_job = NULL;
353 if (rv != ERR_IO_PENDING) 354 if (rv != ERR_IO_PENDING)
354 OnConnectJobComplete(rv, job); 355 OnConnectJobComplete(rv, job);
355 } 356 }
356 357
357 void ClientSocketPoolBaseHelper::CancelRequest( 358 void ClientSocketPoolBaseHelper::CancelRequest(
358 const std::string& group_name, const ClientSocketHandle* handle) { 359 const std::string& group_name, ClientSocketHandle* handle) {
359 // Running callbacks can cause the last outside reference to be released. 360 PendingCallbackMap::iterator callback_it = pending_callback_map_.find(handle);
360 // Hold onto a reference. 361 if (callback_it != pending_callback_map_.end()) {
361 scoped_refptr<ClientSocketPoolBaseHelper> ref_holder(this); 362 int result = callback_it->second.result;
363 pending_callback_map_.erase(callback_it);
364 ClientSocket* socket = handle->release_socket();
365 if (socket) {
366 if (result != OK)
367 socket->Disconnect();
368 ReleaseSocket(handle->group_name(), socket, handle->id());
369 }
370 return;
371 }
362 372
363 CHECK(ContainsKey(group_map_, group_name)); 373 CHECK(ContainsKey(group_map_, group_name));
364 374
365 Group& group = group_map_[group_name]; 375 Group& group = group_map_[group_name];
366 376
367 // Search pending_requests for matching handle. 377 // Search pending_requests for matching handle.
368 RequestQueue::iterator it = group.pending_requests.begin(); 378 RequestQueue::iterator it = group.pending_requests.begin();
369 for (; it != group.pending_requests.end(); ++it) { 379 for (; it != group.pending_requests.end(); ++it) {
370 if ((*it)->handle() == handle) { 380 if ((*it)->handle() == handle) {
371 const Request* req = RemoveRequestFromQueue(it, &group.pending_requests); 381 const Request* req = RemoveRequestFromQueue(it, &group.pending_requests);
(...skipping 19 matching lines...) Expand all
391 const std::string& group_name) const { 401 const std::string& group_name) const {
392 GroupMap::const_iterator i = group_map_.find(group_name); 402 GroupMap::const_iterator i = group_map_.find(group_name);
393 CHECK(i != group_map_.end()); 403 CHECK(i != group_map_.end());
394 404
395 return i->second.idle_sockets.size(); 405 return i->second.idle_sockets.size();
396 } 406 }
397 407
398 LoadState ClientSocketPoolBaseHelper::GetLoadState( 408 LoadState ClientSocketPoolBaseHelper::GetLoadState(
399 const std::string& group_name, 409 const std::string& group_name,
400 const ClientSocketHandle* handle) const { 410 const ClientSocketHandle* handle) const {
411 if (ContainsKey(pending_callback_map_, handle))
412 return LOAD_STATE_CONNECTING;
413
401 if (!ContainsKey(group_map_, group_name)) { 414 if (!ContainsKey(group_map_, group_name)) {
402 NOTREACHED() << "ClientSocketPool does not contain group: " << group_name 415 NOTREACHED() << "ClientSocketPool does not contain group: " << group_name
403 << " for handle: " << handle; 416 << " for handle: " << handle;
404 return LOAD_STATE_IDLE; 417 return LOAD_STATE_IDLE;
405 } 418 }
406 419
407 // Can't use operator[] since it is non-const. 420 // Can't use operator[] since it is non-const.
408 const Group& group = group_map_.find(group_name)->second; 421 const Group& group = group_map_.find(group_name)->second;
409 422
410 // Search pending_requests for matching handle. 423 // Search pending_requests for matching handle.
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
479 } 492 }
480 493
481 void ClientSocketPoolBaseHelper::DecrementIdleCount() { 494 void ClientSocketPoolBaseHelper::DecrementIdleCount() {
482 if (--idle_socket_count_ == 0) 495 if (--idle_socket_count_ == 0)
483 timer_.Stop(); 496 timer_.Stop();
484 } 497 }
485 498
486 void ClientSocketPoolBaseHelper::ReleaseSocket(const std::string& group_name, 499 void ClientSocketPoolBaseHelper::ReleaseSocket(const std::string& group_name,
487 ClientSocket* socket, 500 ClientSocket* socket,
488 int id) { 501 int id) {
489 // Running callbacks can cause the last outside reference to be released.
490 // Hold onto a reference.
491 scoped_refptr<ClientSocketPoolBaseHelper> ref_holder(this);
492
493 GroupMap::iterator i = group_map_.find(group_name); 502 GroupMap::iterator i = group_map_.find(group_name);
494 CHECK(i != group_map_.end()); 503 CHECK(i != group_map_.end());
495 504
496 Group& group = i->second; 505 Group& group = i->second;
497 506
498 CHECK_GT(handed_out_socket_count_, 0); 507 CHECK_GT(handed_out_socket_count_, 0);
499 handed_out_socket_count_--; 508 handed_out_socket_count_--;
500 509
501 CHECK_GT(group.active_socket_count, 0); 510 CHECK_GT(group.active_socket_count, 0);
502 group.active_socket_count--; 511 group.active_socket_count--;
503 512
504 const bool can_reuse = socket->IsConnectedAndIdle() && 513 const bool can_reuse = socket->IsConnectedAndIdle() &&
505 id == pool_generation_number_; 514 id == pool_generation_number_;
506 if (can_reuse) { 515 if (can_reuse) {
507 // Add it to the idle list. 516 // Add it to the idle list.
508 AddIdleSocket(socket, true /* used socket */, &group); 517 AddIdleSocket(socket, true /* used socket */, &group);
509 OnAvailableSocketSlot(group_name, MayHaveStalledGroups()); 518 OnAvailableSocketSlot(group_name, &group);
510 } else { 519 } else {
511 delete socket; 520 delete socket;
512 } 521 }
513 // Check to see if there are stalled groups that can resume now. 522
514 CheckForStalledSocketGroups(); 523 CheckForStalledSocketGroups();
515 } 524 }
516 525
517 void ClientSocketPoolBaseHelper::CheckForStalledSocketGroups() { 526 void ClientSocketPoolBaseHelper::CheckForStalledSocketGroups() {
518 // If we have idle sockets, see if we can give one to the top-stalled group. 527 // If we have idle sockets, see if we can give one to the top-stalled group.
519 std::string top_group_name; 528 std::string top_group_name;
520 Group* top_group = NULL; 529 Group* top_group = NULL;
521 last_stalled_group_count_ = FindTopStalledGroup(&top_group, &top_group_name); 530 if (!FindTopStalledGroup(&top_group, &top_group_name))
522 if (!last_stalled_group_count_)
523 return; 531 return;
524 532
525 if (ReachedMaxSocketsLimit()) { 533 if (ReachedMaxSocketsLimit()) {
526 if (idle_socket_count() > 0) { 534 if (idle_socket_count() > 0) {
527 CloseOneIdleSocket(); 535 CloseOneIdleSocket();
528 } else { 536 } else {
529 // We can't activate more sockets since we're already at our global 537 // We can't activate more sockets since we're already at our global
530 // limit. 538 // limit.
531 return; 539 return;
532 } 540 }
533 } 541 }
534 542
535 // Note: we don't loop on waking stalled groups. If the stalled group is at 543 // Note: we don't loop on waking stalled groups. If the stalled group is at
536 // its limit, may be left with other stalled groups that could be 544 // its limit, may be left with other stalled groups that could be
537 // waken. This isn't optimal, but there is no starvation, so to avoid 545 // woken. This isn't optimal, but there is no starvation, so to avoid
538 // the looping we leave it at this. 546 // the looping we leave it at this.
539 OnAvailableSocketSlot(top_group_name, false); 547 OnAvailableSocketSlot(top_group_name, top_group);
540 }
541
542 bool ClientSocketPoolBaseHelper::MayHaveStalledGroups() {
543 return last_stalled_group_count_ > 0 || ReachedMaxSocketsLimit();
544 } 548 }
545 549
546 // Search for the highest priority pending request, amongst the groups that 550 // Search for the highest priority pending request, amongst the groups that
547 // are not at the |max_sockets_per_group_| limit. Note: for requests with 551 // are not at the |max_sockets_per_group_| limit. Note: for requests with
548 // the same priority, the winner is based on group hash ordering (and not 552 // the same priority, the winner is based on group hash ordering (and not
549 // insertion order). 553 // insertion order).
550 int ClientSocketPoolBaseHelper::FindTopStalledGroup(Group** group, 554 bool ClientSocketPoolBaseHelper::FindTopStalledGroup(Group** group,
551 std::string* group_name) { 555 std::string* group_name) {
552 Group* top_group = NULL; 556 Group* top_group = NULL;
553 const std::string* top_group_name = NULL; 557 const std::string* top_group_name = NULL;
554 int stalled_group_count = 0; 558 bool has_stalled_group = false;
555 for (GroupMap::iterator i = group_map_.begin(); 559 for (GroupMap::iterator i = group_map_.begin();
556 i != group_map_.end(); ++i) { 560 i != group_map_.end(); ++i) {
557 Group& group = i->second; 561 Group& group = i->second;
558 const RequestQueue& queue = group.pending_requests; 562 const RequestQueue& queue = group.pending_requests;
559 if (queue.empty()) 563 if (queue.empty())
560 continue; 564 continue;
561 bool has_unused_slot = 565 if (group.IsStalled(max_sockets_per_group_)) {
562 group.HasAvailableSocketSlot(max_sockets_per_group_) && 566 has_stalled_group = true;
563 group.pending_requests.size() > group.jobs.size();
564 if (has_unused_slot) {
565 stalled_group_count++;
566 bool has_higher_priority = !top_group || 567 bool has_higher_priority = !top_group ||
567 group.TopPendingPriority() < top_group->TopPendingPriority(); 568 group.TopPendingPriority() < top_group->TopPendingPriority();
568 if (has_higher_priority) { 569 if (has_higher_priority) {
569 top_group = &group; 570 top_group = &group;
570 top_group_name = &i->first; 571 top_group_name = &i->first;
571 } 572 }
572 } 573 }
573 } 574 }
575
574 if (top_group) { 576 if (top_group) {
575 *group = top_group; 577 *group = top_group;
576 *group_name = *top_group_name; 578 *group_name = *top_group_name;
577 } 579 }
578 return stalled_group_count; 580 return has_stalled_group;
579 } 581 }
580 582
581 void ClientSocketPoolBaseHelper::OnConnectJobComplete( 583 void ClientSocketPoolBaseHelper::OnConnectJobComplete(
582 int result, ConnectJob* job) { 584 int result, ConnectJob* job) {
583 // Running callbacks can cause the last outside reference to be released.
584 // Hold onto a reference.
585 scoped_refptr<ClientSocketPoolBaseHelper> ref_holder(this);
586
587 DCHECK_NE(ERR_IO_PENDING, result); 585 DCHECK_NE(ERR_IO_PENDING, result);
588 const std::string group_name = job->group_name(); 586 const std::string group_name = job->group_name();
589 GroupMap::iterator group_it = group_map_.find(group_name); 587 GroupMap::iterator group_it = group_map_.find(group_name);
590 CHECK(group_it != group_map_.end()); 588 CHECK(group_it != group_map_.end());
591 Group& group = group_it->second; 589 Group& group = group_it->second;
592 590
593 scoped_ptr<ClientSocket> socket(job->ReleaseSocket()); 591 scoped_ptr<ClientSocket> socket(job->ReleaseSocket());
594 592
595 BoundNetLog job_log = job->net_log(); 593 BoundNetLog job_log = job->net_log();
596 594
597 if (result == OK) { 595 if (result == OK) {
598 DCHECK(socket.get()); 596 DCHECK(socket.get());
599 RemoveConnectJob(job, &group); 597 RemoveConnectJob(job, &group);
600 if (!group.pending_requests.empty()) { 598 if (!group.pending_requests.empty()) {
601 scoped_ptr<const Request> r(RemoveRequestFromQueue( 599 scoped_ptr<const Request> r(RemoveRequestFromQueue(
602 group.pending_requests.begin(), &group.pending_requests)); 600 group.pending_requests.begin(), &group.pending_requests));
603 LogBoundConnectJobToRequest(job_log.source(), r.get()); 601 LogBoundConnectJobToRequest(job_log.source(), r.get());
604 HandOutSocket( 602 HandOutSocket(
605 socket.release(), false /* unused socket */, r->handle(), 603 socket.release(), false /* unused socket */, r->handle(),
606 base::TimeDelta(), &group, r->net_log()); 604 base::TimeDelta(), &group, r->net_log());
607 r->net_log().EndEvent(NetLog::TYPE_SOCKET_POOL, NULL); 605 r->net_log().EndEvent(NetLog::TYPE_SOCKET_POOL, NULL);
608 r->callback()->Run(result); 606 InvokeUserCallbackLater(r->handle(), r->callback(), result);
609 } else { 607 } else {
610 AddIdleSocket(socket.release(), false /* unused socket */, &group); 608 AddIdleSocket(socket.release(), false /* unused socket */, &group);
611 OnAvailableSocketSlot(group_name, MayHaveStalledGroups()); 609 OnAvailableSocketSlot(group_name, &group);
610 CheckForStalledSocketGroups();
612 } 611 }
613 } else { 612 } else {
614 // If we got a socket, it must contain error information so pass that 613 // If we got a socket, it must contain error information so pass that
615 // up so that the caller can retrieve it. 614 // up so that the caller can retrieve it.
616 bool handed_out_socket = false; 615 bool handed_out_socket = false;
617 if (!group.pending_requests.empty()) { 616 if (!group.pending_requests.empty()) {
618 scoped_ptr<const Request> r(RemoveRequestFromQueue( 617 scoped_ptr<const Request> r(RemoveRequestFromQueue(
619 group.pending_requests.begin(), &group.pending_requests)); 618 group.pending_requests.begin(), &group.pending_requests));
620 LogBoundConnectJobToRequest(job_log.source(), r.get()); 619 LogBoundConnectJobToRequest(job_log.source(), r.get());
621 job->GetAdditionalErrorState(r->handle()); 620 job->GetAdditionalErrorState(r->handle());
622 RemoveConnectJob(job, &group); 621 RemoveConnectJob(job, &group);
623 if (socket.get()) { 622 if (socket.get()) {
624 handed_out_socket = true; 623 handed_out_socket = true;
625 HandOutSocket(socket.release(), false /* unused socket */, r->handle(), 624 HandOutSocket(socket.release(), false /* unused socket */, r->handle(),
626 base::TimeDelta(), &group, r->net_log()); 625 base::TimeDelta(), &group, r->net_log());
627 } 626 }
628 r->net_log().EndEvent(NetLog::TYPE_SOCKET_POOL, 627 r->net_log().EndEvent(NetLog::TYPE_SOCKET_POOL,
629 new NetLogIntegerParameter("net_error", result)); 628 new NetLogIntegerParameter("net_error", result));
630 if (socket.get()) { 629 InvokeUserCallbackLater(r->handle(), r->callback(), result);
631 handed_out_socket = true;
632 HandOutSocket(
633 socket.release(), false /* unused socket */, r->handle(),
634 base::TimeDelta(), &group, r->net_log());
635 }
636 r->callback()->Run(result);
637 } else { 630 } else {
638 RemoveConnectJob(job, &group); 631 RemoveConnectJob(job, &group);
639 } 632 }
640 if (!handed_out_socket) 633 if (!handed_out_socket) {
641 OnAvailableSocketSlot(group_name, MayHaveStalledGroups()); 634 OnAvailableSocketSlot(group_name, &group);
635 CheckForStalledSocketGroups();
636 }
642 } 637 }
643 } 638 }
644 639
645 void ClientSocketPoolBaseHelper::OnIPAddressChanged() { 640 void ClientSocketPoolBaseHelper::OnIPAddressChanged() {
646 Flush(); 641 Flush();
647 } 642 }
648 643
649 void ClientSocketPoolBaseHelper::Flush() { 644 void ClientSocketPoolBaseHelper::Flush() {
650 pool_generation_number_++; 645 pool_generation_number_++;
651 CancelAllConnectJobs(); 646 CancelAllConnectJobs();
(...skipping 12 matching lines...) Expand all
664 // If we've got no more jobs for this group, then we no longer need a 659 // If we've got no more jobs for this group, then we no longer need a
665 // backup job either. 660 // backup job either.
666 if (group->jobs.empty()) 661 if (group->jobs.empty())
667 group->CleanupBackupJob(); 662 group->CleanupBackupJob();
668 663
669 DCHECK(job); 664 DCHECK(job);
670 delete job; 665 delete job;
671 } 666 }
672 667
673 void ClientSocketPoolBaseHelper::OnAvailableSocketSlot( 668 void ClientSocketPoolBaseHelper::OnAvailableSocketSlot(
674 const std::string& group_name, bool was_at_socket_limit) { 669 const std::string& group_name, Group* group) {
675 // Go back to the message loop before processing the request wakeup 670 if (!group->pending_requests.empty())
676 // so that we don't get recursive and lengthy stacks. 671 ProcessPendingRequest(group_name, group);
677 MessageLoop::current()->PostTask(FROM_HERE, 672
678 NewRunnableMethod( 673 if (group->IsEmpty())
679 this, 674 group_map_.erase(group_name);
680 &ClientSocketPoolBaseHelper::ProcessPendingRequest,
681 group_name,
682 was_at_socket_limit));
683 } 675 }
684 676
685 void ClientSocketPoolBaseHelper::ProcessPendingRequest( 677 void ClientSocketPoolBaseHelper::ProcessPendingRequest(
686 const std::string& group_name, bool was_at_socket_limit) { 678 const std::string& group_name, Group* group) {
687 GroupMap::iterator it = group_map_.find(group_name); 679 int rv = RequestSocketInternal(group_name,
688 if (it != group_map_.end()) { 680 *group->pending_requests.begin());
689 Group& group = it->second; 681 if (rv != ERR_IO_PENDING) {
690 if (!group.pending_requests.empty()) { 682 scoped_ptr<const Request> request(RemoveRequestFromQueue(
691 int rv = RequestSocketInternal(group_name, 683 group->pending_requests.begin(), &group->pending_requests));
692 *group.pending_requests.begin());
693 if (rv != ERR_IO_PENDING) {
694 scoped_ptr<const Request> request(RemoveRequestFromQueue(
695 group.pending_requests.begin(), &group.pending_requests));
696 684
697 scoped_refptr<NetLog::EventParameters> params; 685 scoped_refptr<NetLog::EventParameters> params;
698 if (rv != OK) 686 if (rv != OK)
699 params = new NetLogIntegerParameter("net_error", rv); 687 params = new NetLogIntegerParameter("net_error", rv);
700 request->net_log().EndEvent(NetLog::TYPE_SOCKET_POOL, params); 688 request->net_log().EndEvent(NetLog::TYPE_SOCKET_POOL, params);
701 request->callback()->Run(rv); 689 InvokeUserCallbackLater(
702 } 690 request->handle(), request->callback(), rv);
703
704 // |group| may no longer be valid after this point. Be careful not to
705 // access it again.
706 if (group.IsEmpty()) {
707 // Delete |group| if no longer needed. |group| will no longer be valid.
708 group_map_.erase(group_name);
709 }
710 }
711 } 691 }
712
713 if (was_at_socket_limit)
714 CheckForStalledSocketGroups();
715 } 692 }
716 693
717 void ClientSocketPoolBaseHelper::HandOutSocket( 694 void ClientSocketPoolBaseHelper::HandOutSocket(
718 ClientSocket* socket, 695 ClientSocket* socket,
719 bool reused, 696 bool reused,
720 ClientSocketHandle* handle, 697 ClientSocketHandle* handle,
721 base::TimeDelta idle_time, 698 base::TimeDelta idle_time,
722 Group* group, 699 Group* group,
723 const BoundNetLog& net_log) { 700 const BoundNetLog& net_log) {
724 DCHECK(socket); 701 DCHECK(socket);
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
799 if (group.IsEmpty()) 776 if (group.IsEmpty())
800 group_map_.erase(i); 777 group_map_.erase(i);
801 778
802 return; 779 return;
803 } 780 }
804 } 781 }
805 782
806 LOG(DFATAL) << "No idle socket found to close!."; 783 LOG(DFATAL) << "No idle socket found to close!.";
807 } 784 }
808 785
786 void ClientSocketPoolBaseHelper::InvokeUserCallbackLater(
787 ClientSocketHandle* handle, CompletionCallback* callback, int rv) {
788 CHECK(!ContainsKey(pending_callback_map_, handle));
789 pending_callback_map_[handle] = CallbackResultPair(callback, rv);
790 MessageLoop::current()->PostTask(
791 FROM_HERE,
792 NewRunnableMethod(
793 this,
794 &ClientSocketPoolBaseHelper::InvokeUserCallback,
795 handle));
796 }
797
798 void ClientSocketPoolBaseHelper::InvokeUserCallback(
799 ClientSocketHandle* handle) {
800 PendingCallbackMap::iterator it = pending_callback_map_.find(handle);
801
802 // Exit if the request has already been cancelled.
803 if (it == pending_callback_map_.end())
804 return;
805
806 CHECK(!handle->is_initialized());
807 CompletionCallback* callback = it->second.callback;
808 int result = it->second.result;
809 pending_callback_map_.erase(it);
810 callback->Run(result);
811 }
812
809 } // namespace internal 813 } // namespace internal
810 814
811 } // namespace net 815 } // 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