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

Unified Diff: net/socket/client_socket_pool_base.cc

Issue 3198009: Revert 57100 - Only create the backup ConnectJob when it is needed.... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 10 years, 4 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/socket/client_socket_pool_base.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/socket/client_socket_pool_base.cc
===================================================================
--- net/socket/client_socket_pool_base.cc (revision 57106)
+++ net/socket/client_socket_pool_base.cc (working copy)
@@ -138,6 +138,7 @@
used_idle_socket_timeout_(used_idle_socket_timeout),
connect_job_factory_(connect_job_factory),
backup_jobs_enabled_(false),
+ ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)),
pool_generation_number_(0),
in_destructor_(false) {
DCHECK_LE(0, max_sockets_per_group);
@@ -187,7 +188,7 @@
const std::string& group_name,
const Request* request) {
request->net_log().BeginEvent(NetLog::TYPE_SOCKET_POOL, NULL);
- Group* group = GetOrCreateGroup(group_name);
+ Group& group = group_map_[group_name];
int rv = RequestSocketInternal(group_name, request);
if (rv != ERR_IO_PENDING) {
@@ -195,7 +196,7 @@
CHECK(!request->handle()->is_initialized());
delete request;
} else {
- InsertRequestIntoQueue(request, group->mutable_pending_requests());
+ InsertRequestIntoQueue(request, &group.pending_requests);
}
return rv;
}
@@ -208,14 +209,14 @@
CHECK(callback);
ClientSocketHandle* const handle = request->handle();
CHECK(handle);
- Group* group = GetOrCreateGroup(group_name);
+ Group& group = group_map_[group_name];
// Try to reuse a socket.
- if (AssignIdleSocketToGroup(request, group))
+ if (AssignIdleSocketToGroup(&group, request))
return OK;
// Can we make another active socket now?
- if (!group->HasAvailableSocketSlot(max_sockets_per_group_)) {
+ if (!group.HasAvailableSocketSlot(max_sockets_per_group_)) {
request->net_log().AddEvent(
NetLog::TYPE_SOCKET_POOL_STALLED_MAX_SOCKETS_PER_GROUP, NULL);
return ERR_IO_PENDING;
@@ -241,26 +242,31 @@
if (rv == OK) {
LogBoundConnectJobToRequest(connect_job->net_log().source(), request);
HandOutSocket(connect_job->ReleaseSocket(), false /* not reused */,
- handle, base::TimeDelta(), group, request->net_log());
+ handle, base::TimeDelta(), &group, request->net_log());
} else if (rv == ERR_IO_PENDING) {
// If we don't have any sockets in this group, set a timer for potentially
// creating a new one. If the SYN is lost, this backup socket may complete
// before the slow socket, improving end user latency.
- if (group->IsEmpty() && !group->HasBackupJob() && backup_jobs_enabled_)
- group->StartBackupSocketTimer(group_name, this);
+ if (group.IsEmpty() && !group.backup_job && backup_jobs_enabled_) {
+ group.backup_job = connect_job_factory_->NewConnectJob(group_name,
+ *request,
+ this);
+ StartBackupSocketTimer(group_name);
+ }
connecting_socket_count_++;
- group->AddJob(connect_job.release());
+ ConnectJob* job = connect_job.release();
+ group.jobs.insert(job);
} else {
LogBoundConnectJobToRequest(connect_job->net_log().source(), request);
connect_job->GetAdditionalErrorState(handle);
ClientSocket* error_socket = connect_job->ReleaseSocket();
if (error_socket) {
HandOutSocket(error_socket, false /* not reused */, handle,
- base::TimeDelta(), group, request->net_log());
- } else if (group->IsEmpty()) {
- RemoveGroup(group_name);
+ base::TimeDelta(), &group, request->net_log());
+ } else if (group.IsEmpty()) {
+ group_map_.erase(group_name);
}
}
@@ -268,12 +274,12 @@
}
bool ClientSocketPoolBaseHelper::AssignIdleSocketToGroup(
- const Request* request, Group* group) {
+ Group* group, const Request* request) {
// Iterate through the list of idle sockets until we find one or exhaust
// the list.
- while (!group->idle_sockets().empty()) {
- IdleSocket idle_socket = group->idle_sockets().back();
- group->mutable_idle_sockets()->pop_back();
+ while (!group->idle_sockets.empty()) {
+ IdleSocket idle_socket = group->idle_sockets.back();
+ group->idle_sockets.pop_back();
DecrementIdleCount();
if (idle_socket.socket->IsConnectedAndIdle()) {
// We found one we can reuse!
@@ -297,6 +303,60 @@
new NetLogSourceParameter("source_dependency", connect_job_source));
}
+void ClientSocketPoolBaseHelper::StartBackupSocketTimer(
+ const std::string& group_name) {
+ CHECK(ContainsKey(group_map_, group_name));
+ Group& group = group_map_[group_name];
+
+ // Only allow one timer pending to create a backup socket.
+ if (group.backup_task)
+ return;
+
+ group.backup_task = method_factory_.NewRunnableMethod(
+ &ClientSocketPoolBaseHelper::OnBackupSocketTimerFired, group_name);
+ MessageLoop::current()->PostDelayedTask(FROM_HERE, group.backup_task,
+ ConnectRetryIntervalMs());
+}
+
+void ClientSocketPoolBaseHelper::OnBackupSocketTimerFired(
+ const std::string& group_name) {
+ CHECK(ContainsKey(group_map_, group_name));
+
+ Group& group = group_map_[group_name];
+
+ CHECK(group.backup_task);
+ group.backup_task = NULL;
+
+ CHECK(group.backup_job);
+
+ // If there are no more jobs pending, there is no work to do.
+ // If we've done our cleanups correctly, this should not happen.
+ if (group.jobs.empty()) {
+ NOTREACHED();
+ return;
+ }
+
+ // If our backup job is waiting on DNS, or if we can't create any sockets
+ // right now due to limits, just reset the timer.
+ if (ReachedMaxSocketsLimit() ||
+ !group.HasAvailableSocketSlot(max_sockets_per_group_) ||
+ (*group.jobs.begin())->GetLoadState() == LOAD_STATE_RESOLVING_HOST) {
+ StartBackupSocketTimer(group_name);
+ return;
+ }
+
+ group.backup_job->net_log().AddEvent(NetLog::TYPE_SOCKET_BACKUP_CREATED,
+ NULL);
+ SIMPLE_STATS_COUNTER("socket.backup_created");
+ int rv = group.backup_job->Connect();
+ connecting_socket_count_++;
+ group.jobs.insert(group.backup_job);
+ ConnectJob* job = group.backup_job;
+ group.backup_job = NULL;
+ if (rv != ERR_IO_PENDING)
+ OnConnectJobComplete(rv, job);
+}
+
void ClientSocketPoolBaseHelper::CancelRequest(
const std::string& group_name, ClientSocketHandle* handle) {
PendingCallbackMap::iterator callback_it = pending_callback_map_.find(handle);
@@ -314,21 +374,20 @@
CHECK(ContainsKey(group_map_, group_name));
- Group* group = GetOrCreateGroup(group_name);
+ Group& group = group_map_[group_name];
// Search pending_requests for matching handle.
- RequestQueue::iterator it = group->mutable_pending_requests()->begin();
- for (; it != group->pending_requests().end(); ++it) {
+ RequestQueue::iterator it = group.pending_requests.begin();
+ for (; it != group.pending_requests.end(); ++it) {
if ((*it)->handle() == handle) {
- const Request* req =
- RemoveRequestFromQueue(it, group->mutable_pending_requests());
+ const Request* req = RemoveRequestFromQueue(it, &group.pending_requests);
req->net_log().AddEvent(NetLog::TYPE_CANCELLED, NULL);
req->net_log().EndEvent(NetLog::TYPE_SOCKET_POOL, NULL);
delete req;
// We let the job run, unless we're at the socket limit.
- if (group->jobs().size() && ReachedMaxSocketsLimit()) {
- RemoveConnectJob(*group->jobs().begin(), group);
+ if (group.jobs.size() && ReachedMaxSocketsLimit()) {
+ RemoveConnectJob(*group.jobs.begin(), &group);
CheckForStalledSocketGroups();
}
break;
@@ -345,7 +404,7 @@
GroupMap::const_iterator i = group_map_.find(group_name);
CHECK(i != group_map_.end());
- return i->second->idle_sockets().size();
+ return i->second.idle_sockets.size();
}
LoadState ClientSocketPoolBaseHelper::GetLoadState(
@@ -361,16 +420,16 @@
}
// Can't use operator[] since it is non-const.
- const Group& group = *group_map_.find(group_name)->second;
+ const Group& group = group_map_.find(group_name)->second;
// Search pending_requests for matching handle.
- RequestQueue::const_iterator it = group.pending_requests().begin();
- for (size_t i = 0; it != group.pending_requests().end(); ++it, ++i) {
+ RequestQueue::const_iterator it = group.pending_requests.begin();
+ for (size_t i = 0; it != group.pending_requests.end(); ++it, ++i) {
if ((*it)->handle() == handle) {
- if (i < group.jobs().size()) {
+ if (i < group.jobs.size()) {
LoadState max_state = LOAD_STATE_IDLE;
- for (ConnectJobSet::const_iterator job_it = group.jobs().begin();
- job_it != group.jobs().end(); ++job_it) {
+ for (ConnectJobSet::const_iterator job_it = group.jobs.begin();
+ job_it != group.jobs.end(); ++job_it) {
max_state = std::max(max_state, (*job_it)->GetLoadState());
}
return max_state;
@@ -412,15 +471,15 @@
GroupMap::iterator i = group_map_.begin();
while (i != group_map_.end()) {
- Group* group = i->second;
+ Group& group = i->second;
- std::deque<IdleSocket>::iterator j = group->mutable_idle_sockets()->begin();
- while (j != group->idle_sockets().end()) {
+ std::deque<IdleSocket>::iterator j = group.idle_sockets.begin();
+ while (j != group.idle_sockets.end()) {
base::TimeDelta timeout =
j->used ? used_idle_socket_timeout_ : unused_idle_socket_timeout_;
if (force || j->ShouldCleanup(now, timeout)) {
delete j->socket;
- j = group->mutable_idle_sockets()->erase(j);
+ j = group.idle_sockets.erase(j);
DecrementIdleCount();
} else {
++j;
@@ -428,36 +487,14 @@
}
// Delete group if no longer needed.
- if (group->IsEmpty()) {
- RemoveGroup(i++);
+ if (group.IsEmpty()) {
+ group_map_.erase(i++);
} else {
++i;
}
}
}
-ClientSocketPoolBaseHelper::Group* ClientSocketPoolBaseHelper::GetOrCreateGroup(
- const std::string& group_name) {
- GroupMap::iterator it = group_map_.find(group_name);
- if (it != group_map_.end())
- return it->second;
- Group* group = new Group;
- group_map_[group_name] = group;
- return group;
-}
-
-void ClientSocketPoolBaseHelper::RemoveGroup(const std::string& group_name) {
- GroupMap::iterator it = group_map_.find(group_name);
- CHECK(it != group_map_.end());
-
- RemoveGroup(it);
-}
-
-void ClientSocketPoolBaseHelper::RemoveGroup(GroupMap::iterator it) {
- delete it->second;
- group_map_.erase(it);
-}
-
void ClientSocketPoolBaseHelper::IncrementIdleCount() {
if (++idle_socket_count_ == 1)
timer_.Start(TimeDelta::FromSeconds(kCleanupInterval), this,
@@ -475,20 +512,20 @@
GroupMap::iterator i = group_map_.find(group_name);
CHECK(i != group_map_.end());
- Group* group = i->second;
+ Group& group = i->second;
CHECK_GT(handed_out_socket_count_, 0);
handed_out_socket_count_--;
- CHECK_GT(group->active_socket_count(), 0);
- group->DecrementActiveSocketCount();
+ CHECK_GT(group.active_socket_count, 0);
+ group.active_socket_count--;
const bool can_reuse = socket->IsConnectedAndIdle() &&
id == pool_generation_number_;
if (can_reuse) {
// Add it to the idle list.
- AddIdleSocket(socket, true /* used socket */, group);
- OnAvailableSocketSlot(group_name, group);
+ AddIdleSocket(socket, true /* used socket */, &group);
+ OnAvailableSocketSlot(group_name, &group);
} else {
delete socket;
}
@@ -531,16 +568,16 @@
bool has_stalled_group = false;
for (GroupMap::iterator i = group_map_.begin();
i != group_map_.end(); ++i) {
- Group* curr_group = i->second;
- const RequestQueue& queue = curr_group->pending_requests();
+ Group& group = i->second;
+ const RequestQueue& queue = group.pending_requests;
if (queue.empty())
continue;
- if (curr_group->IsStalled(max_sockets_per_group_)) {
+ if (group.IsStalled(max_sockets_per_group_)) {
has_stalled_group = true;
bool has_higher_priority = !top_group ||
- curr_group->TopPendingPriority() < top_group->TopPendingPriority();
+ group.TopPendingPriority() < top_group->TopPendingPriority();
if (has_higher_priority) {
- top_group = curr_group;
+ top_group = &group;
top_group_name = &i->first;
}
}
@@ -559,7 +596,7 @@
const std::string group_name = job->group_name();
GroupMap::iterator group_it = group_map_.find(group_name);
CHECK(group_it != group_map_.end());
- Group* group = group_it->second;
+ Group& group = group_it->second;
scoped_ptr<ClientSocket> socket(job->ReleaseSocket());
@@ -567,46 +604,44 @@
if (result == OK) {
DCHECK(socket.get());
- RemoveConnectJob(job, group);
- if (!group->pending_requests().empty()) {
+ RemoveConnectJob(job, &group);
+ if (!group.pending_requests.empty()) {
scoped_ptr<const Request> r(RemoveRequestFromQueue(
- group->mutable_pending_requests()->begin(),
- group->mutable_pending_requests()));
+ group.pending_requests.begin(), &group.pending_requests));
LogBoundConnectJobToRequest(job_log.source(), r.get());
HandOutSocket(
socket.release(), false /* unused socket */, r->handle(),
- base::TimeDelta(), group, r->net_log());
+ base::TimeDelta(), &group, r->net_log());
r->net_log().EndEvent(NetLog::TYPE_SOCKET_POOL, NULL);
InvokeUserCallbackLater(r->handle(), r->callback(), result);
} else {
- AddIdleSocket(socket.release(), false /* unused socket */, group);
- OnAvailableSocketSlot(group_name, group);
+ AddIdleSocket(socket.release(), false /* unused socket */, &group);
+ OnAvailableSocketSlot(group_name, &group);
CheckForStalledSocketGroups();
}
} else {
// If we got a socket, it must contain error information so pass that
// up so that the caller can retrieve it.
bool handed_out_socket = false;
- if (!group->pending_requests().empty()) {
+ if (!group.pending_requests.empty()) {
scoped_ptr<const Request> r(RemoveRequestFromQueue(
- group->mutable_pending_requests()->begin(),
- group->mutable_pending_requests()));
+ group.pending_requests.begin(), &group.pending_requests));
LogBoundConnectJobToRequest(job_log.source(), r.get());
job->GetAdditionalErrorState(r->handle());
- RemoveConnectJob(job, group);
+ RemoveConnectJob(job, &group);
if (socket.get()) {
handed_out_socket = true;
HandOutSocket(socket.release(), false /* unused socket */, r->handle(),
- base::TimeDelta(), group, r->net_log());
+ base::TimeDelta(), &group, r->net_log());
}
r->net_log().EndEvent(NetLog::TYPE_SOCKET_POOL,
new NetLogIntegerParameter("net_error", result));
InvokeUserCallbackLater(r->handle(), r->callback(), result);
} else {
- RemoveConnectJob(job, group);
+ RemoveConnectJob(job, &group);
}
if (!handed_out_socket) {
- OnAvailableSocketSlot(group_name, group);
+ OnAvailableSocketSlot(group_name, &group);
CheckForStalledSocketGroups();
}
}
@@ -627,12 +662,12 @@
connecting_socket_count_--;
DCHECK(group);
- DCHECK(ContainsKey(group->jobs(), job));
- group->RemoveJob(job);
+ DCHECK(ContainsKey(group->jobs, job));
+ group->jobs.erase(job);
// If we've got no more jobs for this group, then we no longer need a
// backup job either.
- if (group->jobs().empty())
+ if (group->jobs.empty())
group->CleanupBackupJob();
DCHECK(job);
@@ -641,21 +676,20 @@
void ClientSocketPoolBaseHelper::OnAvailableSocketSlot(
const std::string& group_name, Group* group) {
- if (!group->pending_requests().empty())
+ if (!group->pending_requests.empty())
ProcessPendingRequest(group_name, group);
if (group->IsEmpty())
- RemoveGroup(group_name);
+ group_map_.erase(group_name);
}
void ClientSocketPoolBaseHelper::ProcessPendingRequest(
const std::string& group_name, Group* group) {
int rv = RequestSocketInternal(group_name,
- *group->pending_requests().begin());
+ *group->pending_requests.begin());
if (rv != ERR_IO_PENDING) {
scoped_ptr<const Request> request(RemoveRequestFromQueue(
- group->mutable_pending_requests()->begin(),
- group->mutable_pending_requests()));
+ group->pending_requests.begin(), &group->pending_requests));
scoped_refptr<NetLog::EventParameters> params;
if (rv != OK)
@@ -691,7 +725,7 @@
"source_dependency", socket->NetLog().source()));
handed_out_socket_count_++;
- group->IncrementActiveSocketCount();
+ group->active_socket_count++;
}
void ClientSocketPoolBaseHelper::AddIdleSocket(
@@ -702,19 +736,26 @@
idle_socket.start_time = base::TimeTicks::Now();
idle_socket.used = used;
- group->mutable_idle_sockets()->push_back(idle_socket);
+ group->idle_sockets.push_back(idle_socket);
IncrementIdleCount();
}
void ClientSocketPoolBaseHelper::CancelAllConnectJobs() {
- for (GroupMap::iterator i = group_map_.begin(); i != group_map_.end(); ++i) {
- Group* group = i->second;
- connecting_socket_count_ -= group->jobs().size();
- group->RemoveAllJobs();
+ for (GroupMap::iterator i = group_map_.begin(); i != group_map_.end();) {
+ Group& group = i->second;
+ connecting_socket_count_ -= group.jobs.size();
+ STLDeleteElements(&group.jobs);
+ if (group.backup_task) {
+ group.backup_task->Cancel();
+ group.backup_task = NULL;
+ }
+
// Delete group if no longer needed.
- if (group->IsEmpty()) {
- RemoveGroup(i);
+ if (group.IsEmpty()) {
+ group_map_.erase(i++);
+ } else {
+ ++i;
}
}
}
@@ -734,16 +775,15 @@
CHECK_GT(idle_socket_count(), 0);
for (GroupMap::iterator i = group_map_.begin(); i != group_map_.end(); ++i) {
- Group* group = i->second;
+ Group& group = i->second;
- if (!group->idle_sockets().empty()) {
- std::deque<IdleSocket>::iterator j =
- group->mutable_idle_sockets()->begin();
+ if (!group.idle_sockets.empty()) {
+ std::deque<IdleSocket>::iterator j = group.idle_sockets.begin();
delete j->socket;
- group->mutable_idle_sockets()->erase(j);
+ group.idle_sockets.erase(j);
DecrementIdleCount();
- if (group->IsEmpty())
- RemoveGroup(i);
+ if (group.IsEmpty())
+ group_map_.erase(i);
return;
}
@@ -779,66 +819,6 @@
callback->Run(result);
}
-ClientSocketPoolBaseHelper::Group::Group()
- : active_socket_count_(0),
- ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {}
-
-ClientSocketPoolBaseHelper::Group::~Group() {
- CleanupBackupJob();
-}
-
-void ClientSocketPoolBaseHelper::Group::StartBackupSocketTimer(
- const std::string& group_name,
- ClientSocketPoolBaseHelper* pool) {
- // Only allow one timer pending to create a backup socket.
- if (!method_factory_.empty())
- return;
-
- MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- method_factory_.NewRunnableMethod(
- &Group::OnBackupSocketTimerFired, group_name, pool),
- pool->ConnectRetryIntervalMs());
-}
-
-void ClientSocketPoolBaseHelper::Group::OnBackupSocketTimerFired(
- std::string group_name,
- ClientSocketPoolBaseHelper* pool) {
- // If there are no more jobs pending, there is no work to do.
- // If we've done our cleanups correctly, this should not happen.
- if (jobs_.empty()) {
- NOTREACHED();
- return;
- }
-
- // If our backup job is waiting on DNS, or if we can't create any sockets
- // right now due to limits, just reset the timer.
- if (pool->ReachedMaxSocketsLimit() ||
- !HasAvailableSocketSlot(pool->max_sockets_per_group_) ||
- (*jobs_.begin())->GetLoadState() == LOAD_STATE_RESOLVING_HOST) {
- StartBackupSocketTimer(group_name, pool);
- return;
- }
-
- ConnectJob* backup_job = pool->connect_job_factory_->NewConnectJob(
- group_name, **pending_requests_.begin(), pool);
- backup_job->net_log().AddEvent(NetLog::TYPE_SOCKET_BACKUP_CREATED, NULL);
- SIMPLE_STATS_COUNTER("socket.backup_created");
- int rv = backup_job->Connect();
- pool->connecting_socket_count_++;
- AddJob(backup_job);
- if (rv != ERR_IO_PENDING)
- pool->OnConnectJobComplete(rv, backup_job);
-}
-
-void ClientSocketPoolBaseHelper::Group::RemoveAllJobs() {
- // Delete active jobs.
- STLDeleteElements(&jobs_);
-
- // Cancel pending backup job.
- method_factory_.RevokeAll();
-}
-
} // namespace internal
} // namespace net
« 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