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

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

Issue 197283012: Retry requests on reused sockets that receive ERR_EMPTY_RESPONSE. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Indentation Created 6 years, 9 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 | Annotate | Revision Log
« no previous file with comments | « net/socket/client_socket_pool_base.h ('k') | no next file » | 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) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/logging.h" 9 #include "base/logging.h"
10 #include "base/message_loop/message_loop.h" 10 #include "base/message_loop/message_loop.h"
11 #include "base/metrics/stats_counters.h" 11 #include "base/metrics/stats_counters.h"
12 #include "base/stl_util.h" 12 #include "base/stl_util.h"
13 #include "base/strings/string_util.h" 13 #include "base/strings/string_util.h"
14 #include "base/time/time.h" 14 #include "base/time/time.h"
15 #include "base/values.h" 15 #include "base/values.h"
16 #include "net/base/net_errors.h" 16 #include "net/base/net_errors.h"
17 #include "net/base/net_log.h" 17 #include "net/base/net_log.h"
18 #include "net/socket/client_socket_handle.h"
19 18
20 using base::TimeDelta; 19 using base::TimeDelta;
21 20
22 namespace net { 21 namespace net {
23 22
24 namespace { 23 namespace {
25 24
26 // Indicate whether we should enable idle socket cleanup timer. When timer is 25 // Indicate whether we should enable idle socket cleanup timer. When timer is
27 // disabled, sockets are closed next time a socket request is made. 26 // disabled, sockets are closed next time a socket request is made.
28 bool g_cleanup_timer_enabled = true; 27 bool g_cleanup_timer_enabled = true;
(...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after
394 393
395 // We couldn't find a socket to reuse, and there's space to allocate one, 394 // We couldn't find a socket to reuse, and there's space to allocate one,
396 // so allocate and connect a new one. 395 // so allocate and connect a new one.
397 scoped_ptr<ConnectJob> connect_job( 396 scoped_ptr<ConnectJob> connect_job(
398 connect_job_factory_->NewConnectJob(group_name, request, this)); 397 connect_job_factory_->NewConnectJob(group_name, request, this));
399 398
400 int rv = connect_job->Connect(); 399 int rv = connect_job->Connect();
401 if (rv == OK) { 400 if (rv == OK) {
402 LogBoundConnectJobToRequest(connect_job->net_log().source(), request); 401 LogBoundConnectJobToRequest(connect_job->net_log().source(), request);
403 if (!preconnecting) { 402 if (!preconnecting) {
404 HandOutSocket(connect_job->PassSocket(), false /* not reused */, 403 HandOutSocket(connect_job->PassSocket(), ClientSocketHandle::UNUSED,
405 connect_job->connect_timing(), handle, base::TimeDelta(), 404 connect_job->connect_timing(), handle, base::TimeDelta(),
406 group, request.net_log()); 405 group, request.net_log());
407 } else { 406 } else {
408 AddIdleSocket(connect_job->PassSocket(), group); 407 AddIdleSocket(connect_job->PassSocket(), group);
409 } 408 }
410 } else if (rv == ERR_IO_PENDING) { 409 } else if (rv == ERR_IO_PENDING) {
411 // If we don't have any sockets in this group, set a timer for potentially 410 // If we don't have any sockets in this group, set a timer for potentially
412 // creating a new one. If the SYN is lost, this backup socket may complete 411 // creating a new one. If the SYN is lost, this backup socket may complete
413 // before the slow socket, improving end user latency. 412 // before the slow socket, improving end user latency.
414 if (connect_backup_jobs_enabled_ && group->IsEmpty()) { 413 if (connect_backup_jobs_enabled_ && group->IsEmpty()) {
415 group->StartBackupJobTimer(group_name, this); 414 group->StartBackupJobTimer(group_name, this);
416 } 415 }
417 416
418 connecting_socket_count_++; 417 connecting_socket_count_++;
419 418
420 group->AddJob(connect_job.Pass(), preconnecting); 419 group->AddJob(connect_job.Pass(), preconnecting);
421 } else { 420 } else {
422 LogBoundConnectJobToRequest(connect_job->net_log().source(), request); 421 LogBoundConnectJobToRequest(connect_job->net_log().source(), request);
423 scoped_ptr<StreamSocket> error_socket; 422 scoped_ptr<StreamSocket> error_socket;
424 if (!preconnecting) { 423 if (!preconnecting) {
425 DCHECK(handle); 424 DCHECK(handle);
426 connect_job->GetAdditionalErrorState(handle); 425 connect_job->GetAdditionalErrorState(handle);
427 error_socket = connect_job->PassSocket(); 426 error_socket = connect_job->PassSocket();
428 } 427 }
429 if (error_socket) { 428 if (error_socket) {
430 HandOutSocket(error_socket.Pass(), false /* not reused */, 429 HandOutSocket(error_socket.Pass(), ClientSocketHandle::UNUSED,
431 connect_job->connect_timing(), handle, base::TimeDelta(), 430 connect_job->connect_timing(), handle, base::TimeDelta(),
432 group, request.net_log()); 431 group, request.net_log());
433 } else if (group->IsEmpty()) { 432 } else if (group->IsEmpty()) {
434 RemoveGroup(group_name); 433 RemoveGroup(group_name);
435 } 434 }
436 } 435 }
437 436
438 return rv; 437 return rv;
439 } 438 }
440 439
(...skipping 28 matching lines...) Expand all
469 468
470 if (idle_socket_it == idle_sockets->end() && !idle_sockets->empty()) 469 if (idle_socket_it == idle_sockets->end() && !idle_sockets->empty())
471 idle_socket_it = idle_sockets->begin(); 470 idle_socket_it = idle_sockets->begin();
472 471
473 if (idle_socket_it != idle_sockets->end()) { 472 if (idle_socket_it != idle_sockets->end()) {
474 DecrementIdleCount(); 473 DecrementIdleCount();
475 base::TimeDelta idle_time = 474 base::TimeDelta idle_time =
476 base::TimeTicks::Now() - idle_socket_it->start_time; 475 base::TimeTicks::Now() - idle_socket_it->start_time;
477 IdleSocket idle_socket = *idle_socket_it; 476 IdleSocket idle_socket = *idle_socket_it;
478 idle_sockets->erase(idle_socket_it); 477 idle_sockets->erase(idle_socket_it);
478 // TODO(davidben): If |idle_time| is under some low watermark, consider
479 // treating as UNUSED rather than UNUSED_IDLE. This will avoid
480 // HttpNetworkTransaction retrying on some errors.
481 ClientSocketHandle::SocketReuseType reuse_type =
482 idle_socket.socket->WasEverUsed() ?
483 ClientSocketHandle::REUSED_IDLE :
484 ClientSocketHandle::UNUSED_IDLE;
479 HandOutSocket( 485 HandOutSocket(
480 scoped_ptr<StreamSocket>(idle_socket.socket), 486 scoped_ptr<StreamSocket>(idle_socket.socket),
481 idle_socket.socket->WasEverUsed(), 487 reuse_type,
482 LoadTimingInfo::ConnectTiming(), 488 LoadTimingInfo::ConnectTiming(),
483 request.handle(), 489 request.handle(),
484 idle_time, 490 idle_time,
485 group, 491 group,
486 request.net_log()); 492 request.net_log());
487 return true; 493 return true;
488 } 494 }
489 495
490 return false; 496 return false;
491 } 497 }
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after
871 // RemoveConnectJob(job, _) must be called by all branches below; 877 // RemoveConnectJob(job, _) must be called by all branches below;
872 // otherwise, |job| will be leaked. 878 // otherwise, |job| will be leaked.
873 879
874 if (result == OK) { 880 if (result == OK) {
875 DCHECK(socket.get()); 881 DCHECK(socket.get());
876 RemoveConnectJob(job, group); 882 RemoveConnectJob(job, group);
877 scoped_ptr<const Request> request = group->PopNextPendingRequest(); 883 scoped_ptr<const Request> request = group->PopNextPendingRequest();
878 if (request) { 884 if (request) {
879 LogBoundConnectJobToRequest(job_log.source(), *request); 885 LogBoundConnectJobToRequest(job_log.source(), *request);
880 HandOutSocket( 886 HandOutSocket(
881 socket.Pass(), false /* unused socket */, connect_timing, 887 socket.Pass(), ClientSocketHandle::UNUSED, connect_timing,
882 request->handle(), base::TimeDelta(), group, request->net_log()); 888 request->handle(), base::TimeDelta(), group, request->net_log());
883 request->net_log().EndEvent(NetLog::TYPE_SOCKET_POOL); 889 request->net_log().EndEvent(NetLog::TYPE_SOCKET_POOL);
884 InvokeUserCallbackLater(request->handle(), request->callback(), result); 890 InvokeUserCallbackLater(request->handle(), request->callback(), result);
885 } else { 891 } else {
886 AddIdleSocket(socket.Pass(), group); 892 AddIdleSocket(socket.Pass(), group);
887 OnAvailableSocketSlot(group_name, group); 893 OnAvailableSocketSlot(group_name, group);
888 CheckForStalledSocketGroups(); 894 CheckForStalledSocketGroups();
889 } 895 }
890 } else { 896 } else {
891 // If we got a socket, it must contain error information so pass that 897 // If we got a socket, it must contain error information so pass that
892 // up so that the caller can retrieve it. 898 // up so that the caller can retrieve it.
893 bool handed_out_socket = false; 899 bool handed_out_socket = false;
894 scoped_ptr<const Request> request = group->PopNextPendingRequest(); 900 scoped_ptr<const Request> request = group->PopNextPendingRequest();
895 if (request) { 901 if (request) {
896 LogBoundConnectJobToRequest(job_log.source(), *request); 902 LogBoundConnectJobToRequest(job_log.source(), *request);
897 job->GetAdditionalErrorState(request->handle()); 903 job->GetAdditionalErrorState(request->handle());
898 RemoveConnectJob(job, group); 904 RemoveConnectJob(job, group);
899 if (socket.get()) { 905 if (socket.get()) {
900 handed_out_socket = true; 906 handed_out_socket = true;
901 HandOutSocket(socket.Pass(), false /* unused socket */, 907 HandOutSocket(socket.Pass(), ClientSocketHandle::UNUSED,
902 connect_timing, request->handle(), base::TimeDelta(), 908 connect_timing, request->handle(), base::TimeDelta(),
903 group, request->net_log()); 909 group, request->net_log());
904 } 910 }
905 request->net_log().EndEventWithNetErrorCode( 911 request->net_log().EndEventWithNetErrorCode(
906 NetLog::TYPE_SOCKET_POOL, result); 912 NetLog::TYPE_SOCKET_POOL, result);
907 InvokeUserCallbackLater(request->handle(), request->callback(), result); 913 InvokeUserCallbackLater(request->handle(), request->callback(), result);
908 } else { 914 } else {
909 RemoveConnectJob(job, group); 915 RemoveConnectJob(job, group);
910 } 916 }
911 if (!handed_out_socket) { 917 if (!handed_out_socket) {
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
956 if (group->IsEmpty()) 962 if (group->IsEmpty())
957 RemoveGroup(group_name); 963 RemoveGroup(group_name);
958 964
959 request->net_log().EndEventWithNetErrorCode(NetLog::TYPE_SOCKET_POOL, rv); 965 request->net_log().EndEventWithNetErrorCode(NetLog::TYPE_SOCKET_POOL, rv);
960 InvokeUserCallbackLater(request->handle(), request->callback(), rv); 966 InvokeUserCallbackLater(request->handle(), request->callback(), rv);
961 } 967 }
962 } 968 }
963 969
964 void ClientSocketPoolBaseHelper::HandOutSocket( 970 void ClientSocketPoolBaseHelper::HandOutSocket(
965 scoped_ptr<StreamSocket> socket, 971 scoped_ptr<StreamSocket> socket,
966 bool reused, 972 ClientSocketHandle::SocketReuseType reuse_type,
967 const LoadTimingInfo::ConnectTiming& connect_timing, 973 const LoadTimingInfo::ConnectTiming& connect_timing,
968 ClientSocketHandle* handle, 974 ClientSocketHandle* handle,
969 base::TimeDelta idle_time, 975 base::TimeDelta idle_time,
970 Group* group, 976 Group* group,
971 const BoundNetLog& net_log) { 977 const BoundNetLog& net_log) {
972 DCHECK(socket); 978 DCHECK(socket);
973 handle->SetSocket(socket.Pass()); 979 handle->SetSocket(socket.Pass());
974 handle->set_is_reused(reused); 980 handle->set_reuse_type(reuse_type);
975 handle->set_idle_time(idle_time); 981 handle->set_idle_time(idle_time);
976 handle->set_pool_id(pool_generation_number_); 982 handle->set_pool_id(pool_generation_number_);
977 handle->set_connect_timing(connect_timing); 983 handle->set_connect_timing(connect_timing);
978 984
979 if (reused) { 985 if (handle->is_reused()) {
980 net_log.AddEvent( 986 net_log.AddEvent(
981 NetLog::TYPE_SOCKET_POOL_REUSED_AN_EXISTING_SOCKET, 987 NetLog::TYPE_SOCKET_POOL_REUSED_AN_EXISTING_SOCKET,
982 NetLog::IntegerCallback( 988 NetLog::IntegerCallback(
983 "idle_ms", static_cast<int>(idle_time.InMilliseconds()))); 989 "idle_ms", static_cast<int>(idle_time.InMilliseconds())));
984 } 990 }
985 991
986 net_log.AddEvent( 992 net_log.AddEvent(
987 NetLog::TYPE_SOCKET_POOL_BOUND_TO_SOCKET, 993 NetLog::TYPE_SOCKET_POOL_BOUND_TO_SOCKET,
988 handle->socket()->NetLog().source().ToEventParametersCallback()); 994 handle->socket()->NetLog().source().ToEventParametersCallback());
989 995
(...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after
1312 pending_requests_.Erase(pointer); 1318 pending_requests_.Erase(pointer);
1313 // If there are no more requests, kill the backup timer. 1319 // If there are no more requests, kill the backup timer.
1314 if (pending_requests_.empty()) 1320 if (pending_requests_.empty())
1315 backup_job_timer_.Stop(); 1321 backup_job_timer_.Stop();
1316 return request.Pass(); 1322 return request.Pass();
1317 } 1323 }
1318 1324
1319 } // namespace internal 1325 } // namespace internal
1320 1326
1321 } // namespace net 1327 } // namespace net
OLDNEW
« no previous file with comments | « net/socket/client_socket_pool_base.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698