OLD | NEW |
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_host_impl.h" | 5 #include "net/http/http_pipelined_host_impl.h" |
6 | 6 |
7 #include "base/stl_util.h" | 7 #include "base/stl_util.h" |
8 #include "net/http/http_pipelined_connection_impl.h" | 8 #include "net/http/http_pipelined_connection_impl.h" |
9 #include "net/http/http_pipelined_stream.h" | 9 #include "net/http/http_pipelined_stream.h" |
10 | 10 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
62 was_npn_negotiated); | 62 was_npn_negotiated); |
63 PipelineInfo info; | 63 PipelineInfo info; |
64 pipelines_.insert(std::make_pair(pipeline, info)); | 64 pipelines_.insert(std::make_pair(pipeline, info)); |
65 return pipeline->CreateNewStream(); | 65 return pipeline->CreateNewStream(); |
66 } | 66 } |
67 | 67 |
68 HttpPipelinedStream* HttpPipelinedHostImpl::CreateStreamOnExistingPipeline() { | 68 HttpPipelinedStream* HttpPipelinedHostImpl::CreateStreamOnExistingPipeline() { |
69 HttpPipelinedConnection* available_pipeline = NULL; | 69 HttpPipelinedConnection* available_pipeline = NULL; |
70 for (PipelineInfoMap::iterator it = pipelines_.begin(); | 70 for (PipelineInfoMap::iterator it = pipelines_.begin(); |
71 it != pipelines_.end(); ++it) { | 71 it != pipelines_.end(); ++it) { |
72 if (it->first->usable() && | 72 if (CanPipelineAcceptRequests(it->first) && |
73 it->first->active() && | |
74 it->first->depth() < GetPipelineCapacity() && | |
75 (!available_pipeline || | 73 (!available_pipeline || |
76 it->first->depth() < available_pipeline->depth())) { | 74 it->first->depth() < available_pipeline->depth())) { |
77 available_pipeline = it->first; | 75 available_pipeline = it->first; |
78 } | 76 } |
79 } | 77 } |
80 if (!available_pipeline) { | 78 if (!available_pipeline) { |
81 return NULL; | 79 return NULL; |
82 } | 80 } |
83 return available_pipeline->CreateNewStream(); | 81 return available_pipeline->CreateNewStream(); |
84 } | 82 } |
85 | 83 |
86 bool HttpPipelinedHostImpl::IsExistingPipelineAvailable() const { | 84 bool HttpPipelinedHostImpl::IsExistingPipelineAvailable() const { |
87 for (PipelineInfoMap::const_iterator it = pipelines_.begin(); | 85 for (PipelineInfoMap::const_iterator it = pipelines_.begin(); |
88 it != pipelines_.end(); ++it) { | 86 it != pipelines_.end(); ++it) { |
89 if (it->first->usable() && | 87 if (CanPipelineAcceptRequests(it->first)) { |
90 it->first->active() && | |
91 it->first->depth() < GetPipelineCapacity()) { | |
92 return true; | 88 return true; |
93 } | 89 } |
94 } | 90 } |
95 return false; | 91 return false; |
96 } | 92 } |
97 | 93 |
98 const HostPortPair& HttpPipelinedHostImpl::origin() const { | 94 const HostPortPair& HttpPipelinedHostImpl::origin() const { |
99 return origin_; | 95 return origin_; |
100 } | 96 } |
101 | 97 |
102 void HttpPipelinedHostImpl::OnPipelineEmpty(HttpPipelinedConnection* pipeline) { | 98 void HttpPipelinedHostImpl::OnPipelineEmpty(HttpPipelinedConnection* pipeline) { |
103 CHECK(ContainsKey(pipelines_, pipeline)); | 99 CHECK(ContainsKey(pipelines_, pipeline)); |
104 pipelines_.erase(pipeline); | 100 pipelines_.erase(pipeline); |
105 delete pipeline; | 101 delete pipeline; |
106 if (pipelines_.empty()) { | 102 if (pipelines_.empty()) { |
107 delegate_->OnHostIdle(this); | 103 delegate_->OnHostIdle(this); |
108 // WARNING: We'll probably be deleted here. | 104 // WARNING: We'll probably be deleted here. |
109 } | 105 } |
110 } | 106 } |
111 | 107 |
112 void HttpPipelinedHostImpl::OnPipelineHasCapacity( | 108 void HttpPipelinedHostImpl::OnPipelineHasCapacity( |
113 HttpPipelinedConnection* pipeline) { | 109 HttpPipelinedConnection* pipeline) { |
114 CHECK(ContainsKey(pipelines_, pipeline)); | 110 CHECK(ContainsKey(pipelines_, pipeline)); |
115 if (pipeline->usable() && | 111 if (CanPipelineAcceptRequests(pipeline)) { |
116 capability_ != INCAPABLE && | |
117 pipeline->depth() < GetPipelineCapacity()) { | |
118 delegate_->OnHostHasAdditionalCapacity(this); | 112 delegate_->OnHostHasAdditionalCapacity(this); |
119 } | 113 } |
120 if (!pipeline->depth()) { | 114 if (!pipeline->depth()) { |
121 OnPipelineEmpty(pipeline); | 115 OnPipelineEmpty(pipeline); |
122 // WARNING: We might be deleted here. | 116 // WARNING: We might be deleted here. |
123 } | 117 } |
124 } | 118 } |
125 | 119 |
126 void HttpPipelinedHostImpl::OnPipelineFeedback( | 120 void HttpPipelinedHostImpl::OnPipelineFeedback( |
127 HttpPipelinedConnection* pipeline, | 121 HttpPipelinedConnection* pipeline, |
128 HttpPipelinedConnection::Feedback feedback) { | 122 HttpPipelinedConnection::Feedback feedback) { |
129 CHECK(ContainsKey(pipelines_, pipeline)); | 123 CHECK(ContainsKey(pipelines_, pipeline)); |
130 switch (feedback) { | 124 switch (feedback) { |
131 case HttpPipelinedConnection::OK: | 125 case HttpPipelinedConnection::OK: |
132 ++pipelines_[pipeline].num_successes; | 126 ++pipelines_[pipeline].num_successes; |
133 if (capability_ == UNKNOWN) { | 127 if (capability_ == UNKNOWN) { |
134 capability_ = PROBABLY_CAPABLE; | 128 capability_ = PROBABLY_CAPABLE; |
135 for (PipelineInfoMap::iterator it = pipelines_.begin(); | 129 NotifyAllPipelinesHaveCapacity(); |
136 it != pipelines_.end(); ++it) { | |
137 OnPipelineHasCapacity(it->first); | |
138 } | |
139 } else if (capability_ == PROBABLY_CAPABLE && | 130 } else if (capability_ == PROBABLY_CAPABLE && |
140 pipelines_[pipeline].num_successes >= | 131 pipelines_[pipeline].num_successes >= |
141 kNumKnownSuccessesThreshold) { | 132 kNumKnownSuccessesThreshold) { |
142 capability_ = CAPABLE; | 133 capability_ = CAPABLE; |
143 delegate_->OnHostDeterminedCapability(this, CAPABLE); | 134 delegate_->OnHostDeterminedCapability(this, CAPABLE); |
144 } | 135 } |
145 break; | 136 break; |
146 | 137 |
147 case HttpPipelinedConnection::PIPELINE_SOCKET_ERROR: | 138 case HttpPipelinedConnection::PIPELINE_SOCKET_ERROR: |
148 case HttpPipelinedConnection::OLD_HTTP_VERSION: | 139 case HttpPipelinedConnection::OLD_HTTP_VERSION: |
(...skipping 20 matching lines...) Expand all Loading... |
169 case UNKNOWN: | 160 case UNKNOWN: |
170 capacity = 1; | 161 capacity = 1; |
171 break; | 162 break; |
172 | 163 |
173 default: | 164 default: |
174 CHECK(false) << "Unkown pipeline capability: " << capability_; | 165 CHECK(false) << "Unkown pipeline capability: " << capability_; |
175 } | 166 } |
176 return capacity; | 167 return capacity; |
177 } | 168 } |
178 | 169 |
| 170 bool HttpPipelinedHostImpl::CanPipelineAcceptRequests( |
| 171 HttpPipelinedConnection* pipeline) const { |
| 172 return capability_ != INCAPABLE && |
| 173 pipeline->usable() && |
| 174 pipeline->active() && |
| 175 pipeline->depth() < GetPipelineCapacity(); |
| 176 } |
| 177 |
| 178 void HttpPipelinedHostImpl::NotifyAllPipelinesHaveCapacity() { |
| 179 // Calling OnPipelineHasCapacity() can have side effects that include |
| 180 // deleting and removing entries from |pipelines_|. |
| 181 PipelineInfoMap pipelines_to_notify = pipelines_; |
| 182 for (PipelineInfoMap::iterator it = pipelines_to_notify.begin(); |
| 183 it != pipelines_to_notify.end(); ++it) { |
| 184 if (pipelines_.find(it->first) != pipelines_.end()) { |
| 185 OnPipelineHasCapacity(it->first); |
| 186 } |
| 187 } |
| 188 } |
| 189 |
179 HttpPipelinedHostImpl::PipelineInfo::PipelineInfo() | 190 HttpPipelinedHostImpl::PipelineInfo::PipelineInfo() |
180 : num_successes(0) { | 191 : num_successes(0) { |
181 } | 192 } |
182 | 193 |
183 } // namespace net | 194 } // namespace net |
OLD | NEW |