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

Side by Side Diff: net/http/http_pipelined_connection_impl.cc

Issue 8586015: Slow start pipelining. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Patch for landing Created 9 years 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
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/http/http_pipelined_connection_impl.h" 5 #include "net/http/http_pipelined_connection_impl.h"
6 6
7 #include "base/message_loop.h" 7 #include "base/message_loop.h"
8 #include "base/stl_util.h" 8 #include "base/stl_util.h"
9 #include "net/base/io_buffer.h" 9 #include "net/base/io_buffer.h"
10 #include "net/http/http_pipelined_stream.h" 10 #include "net/http/http_pipelined_stream.h"
11 #include "net/http/http_request_info.h" 11 #include "net/http/http_request_info.h"
12 #include "net/http/http_response_body_drainer.h" 12 #include "net/http/http_response_body_drainer.h"
13 #include "net/http/http_response_headers.h" 13 #include "net/http/http_response_headers.h"
14 #include "net/http/http_stream_parser.h" 14 #include "net/http/http_stream_parser.h"
15 #include "net/http/http_version.h"
15 #include "net/socket/client_socket_handle.h" 16 #include "net/socket/client_socket_handle.h"
16 17
17 namespace net { 18 namespace net {
18 19
19 HttpPipelinedConnectionImpl::HttpPipelinedConnectionImpl( 20 HttpPipelinedConnectionImpl::HttpPipelinedConnectionImpl(
20 ClientSocketHandle* connection, 21 ClientSocketHandle* connection,
21 HttpPipelinedConnection::Delegate* delegate, 22 HttpPipelinedConnection::Delegate* delegate,
22 const SSLConfig& used_ssl_config, 23 const SSLConfig& used_ssl_config,
23 const ProxyInfo& used_proxy_info, 24 const ProxyInfo& used_proxy_info,
24 const BoundNetLog& net_log, 25 const BoundNetLog& net_log,
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
160 case SEND_STATE_SEND_ACTIVE_REQUEST: 161 case SEND_STATE_SEND_ACTIVE_REQUEST:
161 rv = DoSendActiveRequest(rv); 162 rv = DoSendActiveRequest(rv);
162 break; 163 break;
163 case SEND_STATE_COMPLETE: 164 case SEND_STATE_COMPLETE:
164 rv = DoSendComplete(rv); 165 rv = DoSendComplete(rv);
165 break; 166 break;
166 case SEND_STATE_EVICT_PENDING_REQUESTS: 167 case SEND_STATE_EVICT_PENDING_REQUESTS:
167 rv = DoEvictPendingSendRequests(rv); 168 rv = DoEvictPendingSendRequests(rv);
168 break; 169 break;
169 default: 170 default:
170 NOTREACHED() << "bad send state: " << state; 171 CHECK(false) << "bad send state: " << state;
171 rv = ERR_FAILED; 172 rv = ERR_FAILED;
172 break; 173 break;
173 } 174 }
174 } while (rv != ERR_IO_PENDING && send_next_state_ != SEND_STATE_NONE); 175 } while (rv != ERR_IO_PENDING && send_next_state_ != SEND_STATE_NONE);
175 send_still_on_call_stack_ = false; 176 send_still_on_call_stack_ = false;
176 return rv; 177 return rv;
177 } 178 }
178 179
179 void HttpPipelinedConnectionImpl::OnSendIOCallback(int result) { 180 void HttpPipelinedConnectionImpl::OnSendIOCallback(int result) {
180 CHECK(active_send_request_.get()); 181 CHECK(active_send_request_.get());
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
330 return rv; 331 return rv;
331 case READ_STATE_STREAM_CLOSED: 332 case READ_STATE_STREAM_CLOSED:
332 rv = DoReadStreamClosed(); 333 rv = DoReadStreamClosed();
333 break; 334 break;
334 case READ_STATE_EVICT_PENDING_READS: 335 case READ_STATE_EVICT_PENDING_READS:
335 rv = DoEvictPendingReadHeaders(rv); 336 rv = DoEvictPendingReadHeaders(rv);
336 break; 337 break;
337 case READ_STATE_NONE: 338 case READ_STATE_NONE:
338 break; 339 break;
339 default: 340 default:
340 NOTREACHED() << "bad read state"; 341 CHECK(false) << "bad read state";
341 rv = ERR_FAILED; 342 rv = ERR_FAILED;
342 break; 343 break;
343 } 344 }
344 } while (rv != ERR_IO_PENDING && read_next_state_ != READ_STATE_NONE); 345 } while (rv != ERR_IO_PENDING && read_next_state_ != READ_STATE_NONE);
345 read_still_on_call_stack_ = false; 346 read_still_on_call_stack_ = false;
346 return rv; 347 return rv;
347 } 348 }
348 349
349 void HttpPipelinedConnectionImpl::OnReadIOCallback(int result) { 350 void HttpPipelinedConnectionImpl::OnReadIOCallback(int result) {
350 DoReadHeadersLoop(result); 351 DoReadHeadersLoop(result);
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
387 // Since nobody will read whatever data is on the pipeline associated with 388 // Since nobody will read whatever data is on the pipeline associated with
388 // this closed request, we must shut down the rest of the pipeline. 389 // this closed request, we must shut down the rest of the pipeline.
389 read_next_state_ = READ_STATE_EVICT_PENDING_READS; 390 read_next_state_ = READ_STATE_EVICT_PENDING_READS;
390 break; 391 break;
391 392
392 case STREAM_SENT: 393 case STREAM_SENT:
393 read_next_state_ = READ_STATE_NONE; 394 read_next_state_ = READ_STATE_NONE;
394 break; 395 break;
395 396
396 default: 397 default:
397 NOTREACHED() << "Unexpected read state: " 398 CHECK(false) << "Unexpected read state: "
398 << stream_info_map_[next_id].state; 399 << stream_info_map_[next_id].state;
399 } 400 }
400 401
401 return OK; 402 return OK;
402 } 403 }
403 404
404 int HttpPipelinedConnectionImpl::DoReadHeaders(int result) { 405 int HttpPipelinedConnectionImpl::DoReadHeaders(int result) {
405 CHECK(active_read_id_); 406 CHECK(active_read_id_);
406 CHECK(ContainsKey(stream_info_map_, active_read_id_)); 407 CHECK(ContainsKey(stream_info_map_, active_read_id_));
407 CHECK_EQ(STREAM_READ_PENDING, stream_info_map_[active_read_id_].state); 408 CHECK_EQ(STREAM_READ_PENDING, stream_info_map_[active_read_id_].state);
(...skipping 10 matching lines...) Expand all
418 CHECK_EQ(STREAM_ACTIVE, stream_info_map_[active_read_id_].state); 419 CHECK_EQ(STREAM_ACTIVE, stream_info_map_[active_read_id_].state);
419 420
420 read_next_state_ = READ_STATE_WAITING_FOR_CLOSE; 421 read_next_state_ = READ_STATE_WAITING_FOR_CLOSE;
421 if (result < OK) { 422 if (result < OK) {
422 if (result == ERR_SOCKET_NOT_CONNECTED && completed_one_request_) { 423 if (result == ERR_SOCKET_NOT_CONNECTED && completed_one_request_) {
423 result = ERR_PIPELINE_EVICTION; 424 result = ERR_PIPELINE_EVICTION;
424 } 425 }
425 usable_ = false; 426 usable_ = false;
426 } 427 }
427 428
429 CheckHeadersForPipelineCompatibility(result, active_read_id_);
430
428 if (!read_still_on_call_stack_) { 431 if (!read_still_on_call_stack_) {
429 QueueUserCallback(active_read_id_, 432 QueueUserCallback(active_read_id_,
430 stream_info_map_[active_read_id_].read_headers_callback, 433 stream_info_map_[active_read_id_].read_headers_callback,
431 result, FROM_HERE); 434 result, FROM_HERE);
432 } 435 }
433 436
434 return result; 437 return result;
435 } 438 }
436 439
437 int HttpPipelinedConnectionImpl::DoReadWaitForClose(int result) { 440 int HttpPipelinedConnectionImpl::DoReadWaitForClose(int result) {
438 read_next_state_ = READ_STATE_WAITING_FOR_CLOSE; 441 read_next_state_ = READ_STATE_WAITING_FOR_CLOSE;
439 return result; 442 return result;
440 } 443 }
441 444
442 int HttpPipelinedConnectionImpl::DoReadStreamClosed() { 445 int HttpPipelinedConnectionImpl::DoReadStreamClosed() {
443 CHECK(active_read_id_); 446 CHECK(active_read_id_);
444 CHECK(ContainsKey(stream_info_map_, active_read_id_)); 447 CHECK(ContainsKey(stream_info_map_, active_read_id_));
445 CHECK_EQ(stream_info_map_[active_read_id_].state, STREAM_CLOSED); 448 CHECK_EQ(stream_info_map_[active_read_id_].state, STREAM_CLOSED);
446 active_read_id_ = 0; 449 active_read_id_ = 0;
447 if (!usable_) { 450 if (!usable_) {
451 // TODO(simonjam): Don't wait this long to evict.
448 read_next_state_ = READ_STATE_EVICT_PENDING_READS; 452 read_next_state_ = READ_STATE_EVICT_PENDING_READS;
449 return OK; 453 return OK;
450 } 454 }
451 completed_one_request_ = true; 455 completed_one_request_ = true;
452 MessageLoop::current()->PostTask( 456 MessageLoop::current()->PostTask(
453 FROM_HERE, 457 FROM_HERE,
454 method_factory_.NewRunnableMethod( 458 method_factory_.NewRunnableMethod(
455 &HttpPipelinedConnectionImpl::StartNextDeferredRead)); 459 &HttpPipelinedConnectionImpl::StartNextDeferredRead));
456 read_next_state_ = READ_STATE_NONE; 460 read_next_state_ = READ_STATE_NONE;
457 return OK; 461 return OK;
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
520 case STREAM_READ_EVICTED: 524 case STREAM_READ_EVICTED:
521 stream_info_map_[pipeline_id].state = STREAM_CLOSED; 525 stream_info_map_[pipeline_id].state = STREAM_CLOSED;
522 break; 526 break;
523 527
524 case STREAM_CLOSED: 528 case STREAM_CLOSED:
525 case STREAM_UNUSED: 529 case STREAM_UNUSED:
526 // TODO(simonjam): Why is Close() sometimes called twice? 530 // TODO(simonjam): Why is Close() sometimes called twice?
527 break; 531 break;
528 532
529 default: 533 default:
530 NOTREACHED(); 534 CHECK(false);
531 break; 535 break;
532 } 536 }
533 } 537 }
534 538
535 int HttpPipelinedConnectionImpl::ReadResponseBody( 539 int HttpPipelinedConnectionImpl::ReadResponseBody(
536 int pipeline_id, 540 int pipeline_id,
537 IOBuffer* buf, 541 IOBuffer* buf,
538 int buf_len, 542 int buf_len,
539 OldCompletionCallback* callback) { 543 OldCompletionCallback* callback) {
540 CHECK(ContainsKey(stream_info_map_, pipeline_id)); 544 CHECK(ContainsKey(stream_info_map_, pipeline_id));
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
617 // common. 621 // common.
618 stream->Close(true); 622 stream->Close(true);
619 delete stream; 623 delete stream;
620 return; 624 return;
621 } 625 }
622 HttpResponseBodyDrainer* drainer = new HttpResponseBodyDrainer(stream); 626 HttpResponseBodyDrainer* drainer = new HttpResponseBodyDrainer(stream);
623 drainer->StartWithSize(session, headers->GetContentLength()); 627 drainer->StartWithSize(session, headers->GetContentLength());
624 // |drainer| will delete itself when done. 628 // |drainer| will delete itself when done.
625 } 629 }
626 630
631 void HttpPipelinedConnectionImpl::CheckHeadersForPipelineCompatibility(
632 int result,
633 int pipeline_id) {
634 if (result < OK) {
635 switch (result) {
636 // TODO(simonjam): Ignoring specific errors like this may not work.
637 // Collect metrics to see if this code is useful.
638 case ERR_ABORTED:
639 case ERR_INTERNET_DISCONNECTED:
640 // These errors are no fault of the server.
641 break;
642
643 default:
644 delegate_->OnPipelineFeedback(this, PIPELINE_SOCKET_ERROR);
645 return;
646 }
647 }
648 HttpResponseInfo* info = GetResponseInfo(pipeline_id);
649 const HttpVersion required_version(1, 1);
650 if (info->headers->GetParsedHttpVersion() < required_version) {
651 delegate_->OnPipelineFeedback(this, OLD_HTTP_VERSION);
652 return;
653 }
654 if (!info->headers->IsKeepAlive() || !CanFindEndOfResponse(pipeline_id)) {
655 usable_ = false;
656 delegate_->OnPipelineFeedback(this, MUST_CLOSE_CONNECTION);
657 return;
658 }
659 // TODO(simonjam): We should also check for, and work around, authentication.
660 delegate_->OnPipelineFeedback(this, OK);
661 }
662
627 void HttpPipelinedConnectionImpl::QueueUserCallback( 663 void HttpPipelinedConnectionImpl::QueueUserCallback(
628 int pipeline_id, 664 int pipeline_id,
629 OldCompletionCallback* callback, 665 OldCompletionCallback* callback,
630 int rv, 666 int rv,
631 const tracked_objects::Location& from_here) { 667 const tracked_objects::Location& from_here) {
632 CHECK(!stream_info_map_[pipeline_id].pending_user_callback); 668 CHECK(!stream_info_map_[pipeline_id].pending_user_callback);
633 stream_info_map_[pipeline_id].pending_user_callback = callback; 669 stream_info_map_[pipeline_id].pending_user_callback = callback;
634 MessageLoop::current()->PostTask( 670 MessageLoop::current()->PostTask(
635 from_here, 671 from_here,
636 method_factory_.NewRunnableMethod( 672 method_factory_.NewRunnableMethod(
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
687 HttpPipelinedConnectionImpl::StreamInfo::StreamInfo() 723 HttpPipelinedConnectionImpl::StreamInfo::StreamInfo()
688 : read_headers_callback(NULL), 724 : read_headers_callback(NULL),
689 pending_user_callback(NULL), 725 pending_user_callback(NULL),
690 state(STREAM_CREATED) { 726 state(STREAM_CREATED) {
691 } 727 }
692 728
693 HttpPipelinedConnectionImpl::StreamInfo::~StreamInfo() { 729 HttpPipelinedConnectionImpl::StreamInfo::~StreamInfo() {
694 } 730 }
695 731
696 } // namespace net 732 } // namespace net
OLDNEW
« no previous file with comments | « net/http/http_pipelined_connection_impl.h ('k') | net/http/http_pipelined_connection_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698