Commit 913f8b74 authored by tyoshino's avatar tyoshino Committed by Commit bot

Refactor WebSocketTransportClientSocketPool's socket handing out code

Tries to make the code a little more readable to help debugging the
associated bug.

For the OK result, BoundNetLog::EndEventWithNetErrorCode() was called
after BoundNetLog::EndEvent() in
WebSocketTransportClientSocketPool::RequestSocket(). Fixed this to call
only EndEvent().

Removed pre-condition checks before ActivateStalledRequest() which are
already performed by its while loop.

Added DCHECK_NE(error, OK) to FlushWithError() to make sure OK is never
received from that path.

Reordered some lines.

R=yhirano@chromium.org,mmenke@chromium.org
BUG=642363

Review-Url: https://codereview.chromium.org/2328453002
Cr-Commit-Position: refs/heads/master@{#419127}
parent 6bb34d9b
...@@ -362,37 +362,23 @@ int WebSocketTransportClientSocketPool::RequestSocket( ...@@ -362,37 +362,23 @@ int WebSocketTransportClientSocketPool::RequestSocket(
ConnectionTimeout(), callback, client_socket_factory_, host_resolver_, ConnectionTimeout(), callback, client_socket_factory_, host_resolver_,
handle, &connect_job_delegate_, pool_net_log_, request_net_log)); handle, &connect_job_delegate_, pool_net_log_, request_net_log));
int rv = connect_job->Connect(); int result = connect_job->Connect();
// Regardless of the outcome of |connect_job|, it will always be bound to // Regardless of the outcome of |connect_job|, it will always be bound to
// |handle|, since this pool uses early-binding. So the binding is logged // |handle|, since this pool uses early-binding. So the binding is logged
// here, without waiting for the result. // here, without waiting for the result.
request_net_log.AddEvent( request_net_log.AddEvent(
NetLogEventType::SOCKET_POOL_BOUND_TO_CONNECT_JOB, NetLogEventType::SOCKET_POOL_BOUND_TO_CONNECT_JOB,
connect_job->net_log().source().ToEventParametersCallback()); connect_job->net_log().source().ToEventParametersCallback());
if (rv == OK) {
HandOutSocket(connect_job->PassSocket(), if (result == ERR_IO_PENDING) {
connect_job->connect_timing(),
handle,
request_net_log);
request_net_log.EndEvent(NetLogEventType::SOCKET_POOL);
} else if (rv == ERR_IO_PENDING) {
// TODO(ricea): Implement backup job timer? // TODO(ricea): Implement backup job timer?
AddJob(handle, std::move(connect_job)); AddJob(handle, std::move(connect_job));
} else { } else {
std::unique_ptr<StreamSocket> error_socket; TryHandOutSocket(result, connect_job.get());
connect_job->GetAdditionalErrorState(handle);
error_socket = connect_job->PassSocket();
if (error_socket) {
HandOutSocket(std::move(error_socket), connect_job->connect_timing(),
handle, request_net_log);
}
} }
if (rv != ERR_IO_PENDING) { return result;
request_net_log.EndEventWithNetErrorCode(NetLogEventType::SOCKET_POOL, rv);
}
return rv;
} }
void WebSocketTransportClientSocketPool::RequestSockets( void WebSocketTransportClientSocketPool::RequestSockets(
...@@ -414,8 +400,8 @@ void WebSocketTransportClientSocketPool::CancelRequest( ...@@ -414,8 +400,8 @@ void WebSocketTransportClientSocketPool::CancelRequest(
ReleaseSocket(handle->group_name(), std::move(socket), handle->id()); ReleaseSocket(handle->group_name(), std::move(socket), handle->id());
if (!DeleteJob(handle)) if (!DeleteJob(handle))
pending_callbacks_.erase(handle); pending_callbacks_.erase(handle);
if (!ReachedMaxSocketsLimit() && !stalled_request_queue_.empty())
ActivateStalledRequest(); ActivateStalledRequest();
} }
void WebSocketTransportClientSocketPool::ReleaseSocket( void WebSocketTransportClientSocketPool::ReleaseSocket(
...@@ -425,11 +411,13 @@ void WebSocketTransportClientSocketPool::ReleaseSocket( ...@@ -425,11 +411,13 @@ void WebSocketTransportClientSocketPool::ReleaseSocket(
WebSocketEndpointLockManager::GetInstance()->UnlockSocket(socket.get()); WebSocketEndpointLockManager::GetInstance()->UnlockSocket(socket.get());
CHECK_GT(handed_out_socket_count_, 0); CHECK_GT(handed_out_socket_count_, 0);
--handed_out_socket_count_; --handed_out_socket_count_;
if (!ReachedMaxSocketsLimit() && !stalled_request_queue_.empty())
ActivateStalledRequest(); ActivateStalledRequest();
} }
void WebSocketTransportClientSocketPool::FlushWithError(int error) { void WebSocketTransportClientSocketPool::FlushWithError(int error) {
DCHECK_NE(error, OK);
// Sockets which are in LOAD_STATE_CONNECTING are in danger of unlocking // Sockets which are in LOAD_STATE_CONNECTING are in danger of unlocking
// sockets waiting for the endpoint lock. If they connected synchronously, // sockets waiting for the endpoint lock. If they connected synchronously,
// then OnConnectJobComplete(). The |flushing_| flag tells this object to // then OnConnectJobComplete(). The |flushing_| flag tells this object to
...@@ -506,47 +494,68 @@ bool WebSocketTransportClientSocketPool::IsStalled() const { ...@@ -506,47 +494,68 @@ bool WebSocketTransportClientSocketPool::IsStalled() const {
return !stalled_request_queue_.empty(); return !stalled_request_queue_.empty();
} }
void WebSocketTransportClientSocketPool::OnConnectJobComplete( bool WebSocketTransportClientSocketPool::TryHandOutSocket(
int result, int result,
WebSocketTransportConnectJob* job) { WebSocketTransportConnectJob* job) {
DCHECK_NE(ERR_IO_PENDING, result); DCHECK_NE(result, ERR_IO_PENDING);
std::unique_ptr<StreamSocket> socket = job->PassSocket(); std::unique_ptr<StreamSocket> socket = job->PassSocket();
ClientSocketHandle* const handle = job->handle();
BoundNetLog request_net_log = job->request_net_log();
LoadTimingInfo::ConnectTiming connect_timing = job->connect_timing();
if (result == OK) {
DCHECK(socket);
HandOutSocket(std::move(socket), connect_timing, handle, request_net_log);
request_net_log.EndEvent(NetLogEventType::SOCKET_POOL);
return true;
}
bool handed_out_socket = false;
// If we got a socket, it must contain error information so pass that
// up so that the caller can retrieve it.
job->GetAdditionalErrorState(handle);
if (socket) {
HandOutSocket(std::move(socket), connect_timing, handle, request_net_log);
handed_out_socket = true;
}
request_net_log.EndEventWithNetErrorCode(NetLogEventType::SOCKET_POOL,
result);
return handed_out_socket;
}
void WebSocketTransportClientSocketPool::OnConnectJobComplete(
int result,
WebSocketTransportConnectJob* job) {
DCHECK_NE(ERR_IO_PENDING, result);
// See comment in FlushWithError. // See comment in FlushWithError.
if (flushing_) { if (flushing_) {
std::unique_ptr<StreamSocket> socket = job->PassSocket();
WebSocketEndpointLockManager::GetInstance()->UnlockSocket(socket.get()); WebSocketEndpointLockManager::GetInstance()->UnlockSocket(socket.get());
return; return;
} }
BoundNetLog request_net_log = job->request_net_log(); bool handed_out_socket = TryHandOutSocket(result, job);
CompletionCallback callback = job->callback(); CompletionCallback callback = job->callback();
LoadTimingInfo::ConnectTiming connect_timing = job->connect_timing();
ClientSocketHandle* const handle = job->handle(); ClientSocketHandle* const handle = job->handle();
bool handed_out_socket = false;
if (result == OK) {
DCHECK(socket.get());
handed_out_socket = true;
HandOutSocket(std::move(socket), connect_timing, handle, request_net_log);
request_net_log.EndEvent(NetLogEventType::SOCKET_POOL);
} else {
// If we got a socket, it must contain error information so pass that
// up so that the caller can retrieve it.
job->GetAdditionalErrorState(handle);
if (socket.get()) {
handed_out_socket = true;
HandOutSocket(std::move(socket), connect_timing, handle, request_net_log);
}
request_net_log.EndEventWithNetErrorCode(NetLogEventType::SOCKET_POOL,
result);
}
bool delete_succeeded = DeleteJob(handle); bool delete_succeeded = DeleteJob(handle);
DCHECK(delete_succeeded); DCHECK(delete_succeeded);
if (!handed_out_socket && !stalled_request_queue_.empty() &&
!ReachedMaxSocketsLimit()) job = NULL;
if (!handed_out_socket)
ActivateStalledRequest(); ActivateStalledRequest();
InvokeUserCallbackLater(handle, callback, result); InvokeUserCallbackLater(handle, callback, result);
} }
...@@ -582,9 +591,10 @@ void WebSocketTransportClientSocketPool::HandOutSocket( ...@@ -582,9 +591,10 @@ void WebSocketTransportClientSocketPool::HandOutSocket(
ClientSocketHandle* handle, ClientSocketHandle* handle,
const BoundNetLog& net_log) { const BoundNetLog& net_log) {
DCHECK(socket); DCHECK(socket);
handle->SetSocket(std::move(socket));
DCHECK_EQ(ClientSocketHandle::UNUSED, handle->reuse_type()); DCHECK_EQ(ClientSocketHandle::UNUSED, handle->reuse_type());
DCHECK_EQ(0, handle->idle_time().InMicroseconds()); DCHECK_EQ(0, handle->idle_time().InMicroseconds());
handle->SetSocket(std::move(socket));
handle->set_pool_id(0); handle->set_pool_id(0);
handle->set_connect_timing(connect_timing); handle->set_connect_timing(connect_timing);
...@@ -628,8 +638,6 @@ WebSocketTransportClientSocketPool::LookupConnectJob( ...@@ -628,8 +638,6 @@ WebSocketTransportClientSocketPool::LookupConnectJob(
} }
void WebSocketTransportClientSocketPool::ActivateStalledRequest() { void WebSocketTransportClientSocketPool::ActivateStalledRequest() {
DCHECK(!stalled_request_queue_.empty());
DCHECK(!ReachedMaxSocketsLimit());
// Usually we will only be able to activate one stalled request at a time, // Usually we will only be able to activate one stalled request at a time,
// however if all the connects fail synchronously for some reason, we may be // however if all the connects fail synchronously for some reason, we may be
// able to clear the whole queue at once. // able to clear the whole queue at once.
...@@ -637,11 +645,13 @@ void WebSocketTransportClientSocketPool::ActivateStalledRequest() { ...@@ -637,11 +645,13 @@ void WebSocketTransportClientSocketPool::ActivateStalledRequest() {
StalledRequest request(stalled_request_queue_.front()); StalledRequest request(stalled_request_queue_.front());
stalled_request_queue_.pop_front(); stalled_request_queue_.pop_front();
stalled_request_map_.erase(request.handle); stalled_request_map_.erase(request.handle);
int rv = RequestSocket("ignored", &request.params, request.priority, int rv = RequestSocket("ignored", &request.params, request.priority,
// Stalled requests can't have |respect_limits| // Stalled requests can't have |respect_limits|
// DISABLED. // DISABLED.
RespectLimits::ENABLED, request.handle, RespectLimits::ENABLED, request.handle,
request.callback, request.net_log); request.callback, request.net_log);
// ActivateStalledRequest() never returns synchronously, so it is never // ActivateStalledRequest() never returns synchronously, so it is never
// called re-entrantly. // called re-entrantly.
if (rv != ERR_IO_PENDING) if (rv != ERR_IO_PENDING)
......
...@@ -209,7 +209,9 @@ class NET_EXPORT_PRIVATE WebSocketTransportClientSocketPool ...@@ -209,7 +209,9 @@ class NET_EXPORT_PRIVATE WebSocketTransportClientSocketPool
const CompletionCallback callback; const CompletionCallback callback;
const BoundNetLog net_log; const BoundNetLog net_log;
}; };
friend class ConnectJobDelegate; friend class ConnectJobDelegate;
typedef std::map<const ClientSocketHandle*, WebSocketTransportConnectJob*> typedef std::map<const ClientSocketHandle*, WebSocketTransportConnectJob*>
PendingConnectsMap; PendingConnectsMap;
// This is a list so that we can remove requests from the middle, and also // This is a list so that we can remove requests from the middle, and also
...@@ -219,6 +221,10 @@ class NET_EXPORT_PRIVATE WebSocketTransportClientSocketPool ...@@ -219,6 +221,10 @@ class NET_EXPORT_PRIVATE WebSocketTransportClientSocketPool
typedef std::map<const ClientSocketHandle*, StalledRequestQueue::iterator> typedef std::map<const ClientSocketHandle*, StalledRequestQueue::iterator>
StalledRequestMap; StalledRequestMap;
// Tries to hand out the socket connected by |job|. |result| must be (async)
// result of WebSocketTransportConnectJob::Connect(). Returns true iff it has
// handed out a socket.
bool TryHandOutSocket(int result, WebSocketTransportConnectJob* job);
void OnConnectJobComplete(int result, WebSocketTransportConnectJob* job); void OnConnectJobComplete(int result, WebSocketTransportConnectJob* job);
void InvokeUserCallbackLater(ClientSocketHandle* handle, void InvokeUserCallbackLater(ClientSocketHandle* handle,
const CompletionCallback& callback, const CompletionCallback& callback,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment