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

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

Issue 1212493003: Fix accounting and logging of HttpStream request and job bindings. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@stream-job-logging
Patch Set: comment typo Created 5 years, 6 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/http/http_stream_factory_impl_request.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/http/http_stream_factory_impl_request.h" 5 #include "net/http/http_stream_factory_impl_request.h"
6 6
7 #include "base/callback.h" 7 #include "base/callback.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/stl_util.h" 9 #include "base/stl_util.h"
10 #include "net/http/http_stream_factory_impl_job.h" 10 #include "net/http/http_stream_factory_impl_job.h"
(...skipping 21 matching lines...) Expand all
32 using_spdy_(false) { 32 using_spdy_(false) {
33 DCHECK(factory_); 33 DCHECK(factory_);
34 DCHECK(delegate_); 34 DCHECK(delegate_);
35 35
36 net_log_.BeginEvent(NetLog::TYPE_HTTP_STREAM_REQUEST); 36 net_log_.BeginEvent(NetLog::TYPE_HTTP_STREAM_REQUEST);
37 } 37 }
38 38
39 HttpStreamFactoryImpl::Request::~Request() { 39 HttpStreamFactoryImpl::Request::~Request() {
40 if (bound_job_.get()) 40 if (bound_job_.get())
41 DCHECK(jobs_.empty()); 41 DCHECK(jobs_.empty());
42 else
43 DCHECK(!jobs_.empty());
44 42
45 net_log_.EndEvent(NetLog::TYPE_HTTP_STREAM_REQUEST); 43 net_log_.EndEvent(NetLog::TYPE_HTTP_STREAM_REQUEST);
46 44
47 for (std::set<Job*>::iterator it = jobs_.begin(); it != jobs_.end(); ++it) 45 CancelJobs();
48 factory_->request_map_.erase(*it);
49
50 RemoveRequestFromSpdySessionRequestMap();
51
52 STLDeleteElements(&jobs_);
53 } 46 }
54 47
55 void HttpStreamFactoryImpl::Request::SetSpdySessionKey( 48 void HttpStreamFactoryImpl::Request::SetSpdySessionKey(
56 const SpdySessionKey& spdy_session_key) { 49 const SpdySessionKey& spdy_session_key) {
57 CHECK(!spdy_session_key_.get()); 50 CHECK(!spdy_session_key_.get());
58 spdy_session_key_.reset(new SpdySessionKey(spdy_session_key)); 51 spdy_session_key_.reset(new SpdySessionKey(spdy_session_key));
59 RequestSet& request_set = 52 RequestSet& request_set =
60 factory_->spdy_session_request_map_[spdy_session_key]; 53 factory_->spdy_session_request_map_[spdy_session_key];
61 DCHECK(!ContainsKey(request_set, this)); 54 DCHECK(!ContainsKey(request_set, this));
62 request_set.insert(this); 55 request_set.insert(this);
63 } 56 }
64 57
65 void HttpStreamFactoryImpl::Request::AttachJob(Job* job) { 58 void HttpStreamFactoryImpl::Request::AttachJob(Job* job) {
66 DCHECK(job); 59 DCHECK(job);
67 jobs_.insert(job); 60 jobs_.insert(job);
68 factory_->request_map_[job] = this; 61 factory_->request_map_[job] = this;
69 } 62 }
70 63
71 void HttpStreamFactoryImpl::Request::Complete( 64 void HttpStreamFactoryImpl::Request::Complete(bool was_npn_negotiated,
72 bool was_npn_negotiated, 65 NextProto protocol_negotiated,
73 NextProto protocol_negotiated, 66 bool using_spdy) {
74 bool using_spdy,
75 const BoundNetLog& job_net_log) {
76 DCHECK(!completed_); 67 DCHECK(!completed_);
77 completed_ = true; 68 completed_ = true;
78 was_npn_negotiated_ = was_npn_negotiated; 69 was_npn_negotiated_ = was_npn_negotiated;
79 protocol_negotiated_ = protocol_negotiated; 70 protocol_negotiated_ = protocol_negotiated;
80 using_spdy_ = using_spdy; 71 using_spdy_ = using_spdy;
81 net_log_.AddEvent(
82 NetLog::TYPE_HTTP_STREAM_REQUEST_BOUND_TO_JOB,
83 job_net_log.source().ToEventParametersCallback());
84 job_net_log.AddEvent(
85 NetLog::TYPE_HTTP_STREAM_JOB_BOUND_TO_REQUEST,
86 net_log_.source().ToEventParametersCallback());
87 } 72 }
88 73
89 void HttpStreamFactoryImpl::Request::OnStreamReady( 74 void HttpStreamFactoryImpl::Request::OnStreamReady(
90 Job* job, 75 Job* job,
91 const SSLConfig& used_ssl_config, 76 const SSLConfig& used_ssl_config,
92 const ProxyInfo& used_proxy_info, 77 const ProxyInfo& used_proxy_info,
93 HttpStream* stream) { 78 HttpStream* stream) {
94 DCHECK(!factory_->for_websockets_); 79 DCHECK(!factory_->for_websockets_);
95 DCHECK(stream); 80 DCHECK(stream);
96 DCHECK(completed_); 81 DCHECK(completed_);
(...skipping 17 matching lines...) Expand all
114 } 99 }
115 100
116 void HttpStreamFactoryImpl::Request::OnStreamFailed( 101 void HttpStreamFactoryImpl::Request::OnStreamFailed(
117 Job* job, 102 Job* job,
118 int status, 103 int status,
119 const SSLConfig& used_ssl_config, 104 const SSLConfig& used_ssl_config,
120 SSLFailureState ssl_failure_state) { 105 SSLFailureState ssl_failure_state) {
121 DCHECK_NE(OK, status); 106 DCHECK_NE(OK, status);
122 DCHECK(job); 107 DCHECK(job);
123 if (!bound_job_.get()) { 108 if (!bound_job_.get()) {
124 // Hey, we've got other jobs! Maybe one of them will succeed, let's just
125 // ignore this failure.
126 if (jobs_.size() > 1) { 109 if (jobs_.size() > 1) {
110 // Hey, we've got other jobs! Maybe one of them will succeed, let's just
111 // ignore this failure.
127 jobs_.erase(job); 112 jobs_.erase(job);
128 factory_->request_map_.erase(job); 113 factory_->request_map_.erase(job);
129 // Notify all the other jobs that this one failed. 114 // Notify all the other jobs that this one failed.
130 for (std::set<Job*>::iterator it = jobs_.begin(); it != jobs_.end(); ++it) 115 for (std::set<Job*>::iterator it = jobs_.begin(); it != jobs_.end(); ++it)
131 (*it)->MarkOtherJobComplete(*job); 116 (*it)->MarkOtherJobComplete(*job);
132 delete job; 117 delete job;
133 return; 118 return;
134 } else { 119 } else {
135 bound_job_.reset(job); 120 BindJob(job);
136 jobs_.erase(job);
137 DCHECK(jobs_.empty());
138 factory_->request_map_.erase(job);
139 } 121 }
140 } else { 122 } else {
141 DCHECK(jobs_.empty()); 123 DCHECK(jobs_.empty());
142 } 124 }
143 delegate_->OnStreamFailed(status, used_ssl_config, ssl_failure_state); 125 delegate_->OnStreamFailed(status, used_ssl_config, ssl_failure_state);
144 } 126 }
145 127
146 void HttpStreamFactoryImpl::Request::OnCertificateError( 128 void HttpStreamFactoryImpl::Request::OnCertificateError(
147 Job* job, 129 Job* job,
148 int status, 130 int status,
149 const SSLConfig& used_ssl_config, 131 const SSLConfig& used_ssl_config,
150 const SSLInfo& ssl_info) { 132 const SSLInfo& ssl_info) {
151 DCHECK_NE(OK, status); 133 DCHECK_NE(OK, status);
152 if (!bound_job_.get()) 134 if (!bound_job_.get())
153 OrphanJobsExcept(job); 135 BindJob(job);
154 else 136 else
155 DCHECK(jobs_.empty()); 137 DCHECK(jobs_.empty());
156 delegate_->OnCertificateError(status, used_ssl_config, ssl_info); 138 delegate_->OnCertificateError(status, used_ssl_config, ssl_info);
157 } 139 }
158 140
159 void HttpStreamFactoryImpl::Request::OnNeedsProxyAuth( 141 void HttpStreamFactoryImpl::Request::OnNeedsProxyAuth(
160 Job* job, 142 Job* job,
161 const HttpResponseInfo& proxy_response, 143 const HttpResponseInfo& proxy_response,
162 const SSLConfig& used_ssl_config, 144 const SSLConfig& used_ssl_config,
163 const ProxyInfo& used_proxy_info, 145 const ProxyInfo& used_proxy_info,
164 HttpAuthController* auth_controller) { 146 HttpAuthController* auth_controller) {
165 if (!bound_job_.get()) 147 if (!bound_job_.get())
166 OrphanJobsExcept(job); 148 BindJob(job);
167 else 149 else
168 DCHECK(jobs_.empty()); 150 DCHECK(jobs_.empty());
169 delegate_->OnNeedsProxyAuth( 151 delegate_->OnNeedsProxyAuth(
170 proxy_response, used_ssl_config, used_proxy_info, auth_controller); 152 proxy_response, used_ssl_config, used_proxy_info, auth_controller);
171 } 153 }
172 154
173 void HttpStreamFactoryImpl::Request::OnNeedsClientAuth( 155 void HttpStreamFactoryImpl::Request::OnNeedsClientAuth(
174 Job* job, 156 Job* job,
175 const SSLConfig& used_ssl_config, 157 const SSLConfig& used_ssl_config,
176 SSLCertRequestInfo* cert_info) { 158 SSLCertRequestInfo* cert_info) {
177 if (!bound_job_.get()) 159 if (!bound_job_.get())
178 OrphanJobsExcept(job); 160 BindJob(job);
179 else 161 else
180 DCHECK(jobs_.empty()); 162 DCHECK(jobs_.empty());
181 delegate_->OnNeedsClientAuth(used_ssl_config, cert_info); 163 delegate_->OnNeedsClientAuth(used_ssl_config, cert_info);
182 } 164 }
183 165
184 void HttpStreamFactoryImpl::Request::OnHttpsProxyTunnelResponse( 166 void HttpStreamFactoryImpl::Request::OnHttpsProxyTunnelResponse(
185 Job *job, 167 Job *job,
186 const HttpResponseInfo& response_info, 168 const HttpResponseInfo& response_info,
187 const SSLConfig& used_ssl_config, 169 const SSLConfig& used_ssl_config,
188 const ProxyInfo& used_proxy_info, 170 const ProxyInfo& used_proxy_info,
189 HttpStream* stream) { 171 HttpStream* stream) {
190 if (!bound_job_.get()) 172 if (!bound_job_.get())
191 OrphanJobsExcept(job); 173 BindJob(job);
192 else 174 else
193 DCHECK(jobs_.empty()); 175 DCHECK(jobs_.empty());
194 delegate_->OnHttpsProxyTunnelResponse( 176 delegate_->OnHttpsProxyTunnelResponse(
195 response_info, used_ssl_config, used_proxy_info, stream); 177 response_info, used_ssl_config, used_proxy_info, stream);
196 } 178 }
197 179
198 int HttpStreamFactoryImpl::Request::RestartTunnelWithProxyAuth( 180 int HttpStreamFactoryImpl::Request::RestartTunnelWithProxyAuth(
199 const AuthCredentials& credentials) { 181 const AuthCredentials& credentials) {
200 DCHECK(bound_job_.get()); 182 DCHECK(bound_job_.get());
201 return bound_job_->RestartTunnelWithProxyAuth(credentials); 183 return bound_job_->RestartTunnelWithProxyAuth(credentials);
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
274 bool direct) { 256 bool direct) {
275 DCHECK(job); 257 DCHECK(job);
276 DCHECK(job->using_spdy()); 258 DCHECK(job->using_spdy());
277 259
278 // Note: |spdy_session| may be NULL. In that case, |delegate_| should still 260 // Note: |spdy_session| may be NULL. In that case, |delegate_| should still
279 // receive |stream| so the error propogates up correctly, however there is no 261 // receive |stream| so the error propogates up correctly, however there is no
280 // point in broadcasting |spdy_session| to other requests. 262 // point in broadcasting |spdy_session| to other requests.
281 263
282 // The first case is the usual case. 264 // The first case is the usual case.
283 if (!bound_job_.get()) { 265 if (!bound_job_.get()) {
284 OrphanJobsExcept(job); 266 BindJob(job);
285 } else { // This is the case for HTTPS proxy tunneling. 267 } else { // This is the case for HTTPS proxy tunneling.
286 DCHECK_EQ(bound_job_.get(), job); 268 DCHECK_EQ(bound_job_.get(), job);
287 DCHECK(jobs_.empty()); 269 DCHECK(jobs_.empty());
288 } 270 }
289 271
290 // Cache these values in case the job gets deleted. 272 // Cache these values in case the job gets deleted.
291 const SSLConfig used_ssl_config = job->server_ssl_config(); 273 const SSLConfig used_ssl_config = job->server_ssl_config();
292 const ProxyInfo used_proxy_info = job->proxy_info(); 274 const ProxyInfo used_proxy_info = job->proxy_info();
293 const bool was_npn_negotiated = job->was_npn_negotiated(); 275 const bool was_npn_negotiated = job->was_npn_negotiated();
294 const NextProto protocol_negotiated = 276 const NextProto protocol_negotiated =
295 job->protocol_negotiated(); 277 job->protocol_negotiated();
296 const bool using_spdy = job->using_spdy(); 278 const bool using_spdy = job->using_spdy();
297 const BoundNetLog net_log = job->net_log(); 279 const BoundNetLog net_log = job->net_log();
298 280
299 Complete(was_npn_negotiated, protocol_negotiated, using_spdy, net_log); 281 Complete(was_npn_negotiated, protocol_negotiated, using_spdy);
300 282
301 // Cache this so we can still use it if the request is deleted. 283 // Cache this so we can still use it if the request is deleted.
302 HttpStreamFactoryImpl* factory = factory_; 284 HttpStreamFactoryImpl* factory = factory_;
303 if (factory->for_websockets_) { 285 if (factory->for_websockets_) {
304 // TODO(ricea): Re-instate this code when WebSockets over SPDY is 286 // TODO(ricea): Re-instate this code when WebSockets over SPDY is
305 // implemented. 287 // implemented.
306 NOTREACHED(); 288 NOTREACHED();
307 } else { 289 } else {
308 delegate_->OnStreamReady(job->server_ssl_config(), job->proxy_info(), 290 delegate_->OnStreamReady(job->server_ssl_config(), job->proxy_info(),
309 stream.release()); 291 stream.release());
(...skipping 10 matching lines...) Expand all
320 net_log); 302 net_log);
321 } 303 }
322 } 304 }
323 305
324 void HttpStreamFactoryImpl::Request::AddConnectionAttempts( 306 void HttpStreamFactoryImpl::Request::AddConnectionAttempts(
325 const ConnectionAttempts& attempts) { 307 const ConnectionAttempts& attempts) {
326 for (const auto& attempt : attempts) 308 for (const auto& attempt : attempts)
327 connection_attempts_.push_back(attempt); 309 connection_attempts_.push_back(attempt);
328 } 310 }
329 311
330 void HttpStreamFactoryImpl::Request::OrphanJobsExcept(Job* job) { 312 void HttpStreamFactoryImpl::Request::BindJob(Job* job) {
331 DCHECK(job); 313 DCHECK(job);
332 DCHECK(!bound_job_.get()); 314 DCHECK(!bound_job_.get());
333 DCHECK(ContainsKey(jobs_, job)); 315 DCHECK(ContainsKey(jobs_, job));
334 bound_job_.reset(job); 316 bound_job_.reset(job);
335 jobs_.erase(job); 317 jobs_.erase(job);
336 factory_->request_map_.erase(job); 318 factory_->request_map_.erase(job);
337 319
320 net_log_.AddEvent(NetLog::TYPE_HTTP_STREAM_REQUEST_BOUND_TO_JOB,
321 job->net_log().source().ToEventParametersCallback());
322 job->net_log().AddEvent(NetLog::TYPE_HTTP_STREAM_JOB_BOUND_TO_REQUEST,
323 net_log_.source().ToEventParametersCallback());
324
338 OrphanJobs(); 325 OrphanJobs();
339 } 326 }
340 327
341 void HttpStreamFactoryImpl::Request::OrphanJobs() { 328 void HttpStreamFactoryImpl::Request::OrphanJobs() {
342 RemoveRequestFromSpdySessionRequestMap(); 329 RemoveRequestFromSpdySessionRequestMap();
343 330
344 std::set<Job*> tmp; 331 std::set<Job*> tmp;
345 tmp.swap(jobs_); 332 tmp.swap(jobs_);
346 333
347 for (std::set<Job*>::iterator it = tmp.begin(); it != tmp.end(); ++it) 334 for (Job* job : tmp)
348 factory_->OrphanJob(*it, this); 335 factory_->OrphanJob(job, this);
336 }
337
338 void HttpStreamFactoryImpl::Request::CancelJobs() {
339 RemoveRequestFromSpdySessionRequestMap();
340
341 std::set<Job*> tmp;
342 tmp.swap(jobs_);
343
344 for (Job* job : tmp) {
345 factory_->request_map_.erase(job);
346 delete job;
347 }
349 } 348 }
350 349
351 void HttpStreamFactoryImpl::Request::OnJobSucceeded(Job* job) { 350 void HttpStreamFactoryImpl::Request::OnJobSucceeded(Job* job) {
352 // |job| should only be NULL if we're being serviced by a late bound 351 // |job| should only be NULL if we're being serviced by a late bound
353 // SpdySession (one that was not created by a job in our |jobs_| set). 352 // SpdySession (one that was not created by a job in our |jobs_| set).
354 if (!job) { 353 if (!job) {
355 DCHECK(!bound_job_.get()); 354 DCHECK(!bound_job_.get());
356 DCHECK(!jobs_.empty()); 355 DCHECK(!jobs_.empty());
357 // NOTE(willchan): We do *NOT* call OrphanJobs() here. The reason is because 356 // NOTE(willchan): We do *NOT* call OrphanJobs() here. The reason is because
358 // we *WANT* to cancel the unnecessary Jobs from other requests if another 357 // we *WANT* to cancel the unnecessary Jobs from other requests if another
359 // Job completes first. 358 // Job completes first.
360 // TODO(mbelshe): Revisit this when we implement ip connection pooling of 359 // TODO(mbelshe): Revisit this when we implement ip connection pooling of
361 // SpdySessions. Do we want to orphan the jobs for a different hostname so 360 // SpdySessions. Do we want to orphan the jobs for a different hostname so
362 // they complete? Or do we want to prevent connecting a new SpdySession if 361 // they complete? Or do we want to prevent connecting a new SpdySession if
363 // we've already got one available for a different hostname where the ip 362 // we've already got one available for a different hostname where the ip
364 // address matches up? 363 // address matches up?
364 CancelJobs();
365 return; 365 return;
366 } 366 }
367 if (!bound_job_.get()) { 367 if (!bound_job_.get()) {
368 if (jobs_.size() > 1) 368 if (jobs_.size() > 1)
369 job->ReportJobSucceededForRequest(); 369 job->ReportJobSucceededForRequest();
370 // Notify all the other jobs that this one succeeded. 370 // Notify all the other jobs that this one succeeded.
371 for (std::set<Job*>::iterator it = jobs_.begin(); it != jobs_.end(); ++it) { 371 for (std::set<Job*>::iterator it = jobs_.begin(); it != jobs_.end(); ++it) {
372 if (*it != job) { 372 if (*it != job) {
373 (*it)->MarkOtherJobComplete(*job); 373 (*it)->MarkOtherJobComplete(*job);
374 } 374 }
375 } 375 }
376 // We may have other jobs in |jobs_|. For example, if we start multiple jobs 376 // We may have other jobs in |jobs_|. For example, if we start multiple jobs
377 // for Alternate-Protocol. 377 // for Alternate-Protocol.
378 OrphanJobsExcept(job); 378 BindJob(job);
379 return; 379 return;
380 } 380 }
381 DCHECK(jobs_.empty()); 381 DCHECK(jobs_.empty());
382 } 382 }
383 383
384 } // namespace net 384 } // namespace net
OLDNEW
« no previous file with comments | « net/http/http_stream_factory_impl_request.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698