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

Unified Diff: net/socket/client_socket_pool_base.cc

Issue 18796003: When an idle socket is added back to a socket pool, check for stalled jobs in lower pools (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Undo somewhat tangential change Created 7 years, 5 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
Index: net/socket/client_socket_pool_base.cc
===================================================================
--- net/socket/client_socket_pool_base.cc (revision 211652)
+++ net/socket/client_socket_pool_base.cc (working copy)
@@ -161,6 +161,7 @@
ClientSocketPoolBaseHelper::Request::~Request() {}
ClientSocketPoolBaseHelper::ClientSocketPoolBaseHelper(
+ HigherLayeredPool* pool,
int max_sockets,
int max_sockets_per_group,
base::TimeDelta unused_idle_socket_timeout,
@@ -177,6 +178,7 @@
connect_job_factory_(connect_job_factory),
connect_backup_jobs_enabled_(false),
pool_generation_number_(0),
+ pool_(pool),
weak_factory_(this) {
DCHECK_LE(0, max_sockets_per_group);
DCHECK_LE(max_sockets_per_group, max_sockets);
@@ -192,9 +194,16 @@
DCHECK(group_map_.empty());
DCHECK(pending_callback_map_.empty());
DCHECK_EQ(0, connecting_socket_count_);
- CHECK(higher_layer_pools_.empty());
+ CHECK(higher_pools_.empty());
NetworkChangeNotifier::RemoveIPAddressObserver(this);
+
+ // Remove from lower layer pools.
+ for (std::set<LowerLayeredPool*>::iterator it = lower_pools_.begin();
+ it != lower_pools_.end();
+ ++it) {
+ (*it)->RemoveHigherLayeredPool(pool_);
+ }
}
ClientSocketPoolBaseHelper::CallbackResultPair::CallbackResultPair()
@@ -234,18 +243,55 @@
return req;
}
-void ClientSocketPoolBaseHelper::AddLayeredPool(LayeredPool* pool) {
- CHECK(pool);
- CHECK(!ContainsKey(higher_layer_pools_, pool));
- higher_layer_pools_.insert(pool);
+bool ClientSocketPoolBaseHelper::IsStalled() const {
+ // If a lower layer pool is stalled, consider |this| stalled as well.
Ryan Hamilton 2013/07/21 14:53:54 This seems like mostly a good idea, but how does i
mmenke 2013/07/22 20:13:33 SpdySessions can never be stalled. They aren't co
Ryan Hamilton 2013/07/22 20:22:46 Works for me. FWIW, there is a streams/session li
mmenke 2013/07/24 19:05:23 Yea, I don't think so - that would need to be deal
+ for (std::set<LowerLayeredPool*>::const_iterator it = lower_pools_.begin();
+ it != lower_pools_.end();
+ ++it) {
+ if ((*it)->IsStalled())
+ return true;
+ }
+
+ // If we are not using |max_sockets_|, then clearly we are not stalled
+ if ((handed_out_socket_count_ + connecting_socket_count_) < max_sockets_)
+ return false;
+ // So in order to be stalled we need to be using |max_sockets_| AND
+ // we need to have a request that is actually stalled on the global
+ // socket limit. To find such a request, we look for a group that
+ // a has more requests that jobs AND where the number of jobs is less
+ // than |max_sockets_per_group_|. (If the number of jobs is equal to
+ // |max_sockets_per_group_|, then the request is stalled on the group,
+ // which does not count.)
+ for (GroupMap::const_iterator it = group_map_.begin();
+ it != group_map_.end(); ++it) {
+ if (it->second->IsStalledOnPoolMaxSockets(max_sockets_per_group_))
+ return true;
+ }
+ return false;
}
-void ClientSocketPoolBaseHelper::RemoveLayeredPool(LayeredPool* pool) {
- CHECK(pool);
- CHECK(ContainsKey(higher_layer_pools_, pool));
- higher_layer_pools_.erase(pool);
+void ClientSocketPoolBaseHelper::AddLowerLayeredPool(
+ LowerLayeredPool* lower_pool) {
+ DCHECK(pool_);
+ CHECK(!ContainsKey(lower_pools_, lower_pool));
+ lower_pools_.insert(lower_pool);
+ lower_pool->AddHigherLayeredPool(pool_);
}
+void ClientSocketPoolBaseHelper::AddHigherLayeredPool(
+ HigherLayeredPool* higher_pool) {
+ CHECK(higher_pool);
+ CHECK(!ContainsKey(higher_pools_, higher_pool));
+ higher_pools_.insert(higher_pool);
+}
+
+void ClientSocketPoolBaseHelper::RemoveHigherLayeredPool(
+ HigherLayeredPool* higher_pool) {
+ CHECK(higher_pool);
+ CHECK(ContainsKey(higher_pools_, higher_pool));
+ higher_pools_.erase(higher_pool);
+}
+
int ClientSocketPoolBaseHelper::RequestSocket(
const std::string& group_name,
const Request* request) {
@@ -784,8 +830,18 @@
// If we have idle sockets, see if we can give one to the top-stalled group.
std::string top_group_name;
Group* top_group = NULL;
- if (!FindTopStalledGroup(&top_group, &top_group_name))
+ if (!FindTopStalledGroup(&top_group, &top_group_name)) {
+ // There may still be a stalled group in a lower level pool.
+ for (std::set<LowerLayeredPool*>::iterator it = lower_pools_.begin();
+ it != lower_pools_.end();
+ ++it) {
+ if ((*it)->IsStalled()) {
+ CloseOneIdleSocket();
+ break;
+ }
+ }
return;
+ }
if (ReachedMaxSocketsLimit()) {
if (idle_socket_count() > 0) {
@@ -915,25 +971,6 @@
CancelAllRequestsWithError(error);
}
-bool ClientSocketPoolBaseHelper::IsStalled() const {
- // If we are not using |max_sockets_|, then clearly we are not stalled
- if ((handed_out_socket_count_ + connecting_socket_count_) < max_sockets_)
- return false;
- // So in order to be stalled we need to be using |max_sockets_| AND
- // we need to have a request that is actually stalled on the global
- // socket limit. To find such a request, we look for a group that
- // a has more requests that jobs AND where the number of jobs is less
- // than |max_sockets_per_group_|. (If the number of jobs is equal to
- // |max_sockets_per_group_|, then the request is stalled on the group,
- // which does not count.)
- for (GroupMap::const_iterator it = group_map_.begin();
- it != group_map_.end(); ++it) {
- if (it->second->IsStalledOnPoolMaxSockets(max_sockets_per_group_))
- return true;
- }
- return false;
-}
-
void ClientSocketPoolBaseHelper::RemoveConnectJob(ConnectJob* job,
Group* group) {
CHECK_GT(connecting_socket_count_, 0);
@@ -1101,12 +1138,12 @@
return false;
}
-bool ClientSocketPoolBaseHelper::CloseOneIdleConnectionInLayeredPool() {
+bool ClientSocketPoolBaseHelper::CloseOneIdleConnectionInHigherLayeredPool() {
// This pool doesn't have any idle sockets. It's possible that a pool at a
// higher layer is holding one of this sockets active, but it's actually idle.
// Query the higher layers.
- for (std::set<LayeredPool*>::const_iterator it = higher_layer_pools_.begin();
- it != higher_layer_pools_.end(); ++it) {
+ for (std::set<HigherLayeredPool*>::const_iterator it = higher_pools_.begin();
+ it != higher_pools_.end(); ++it) {
if ((*it)->CloseOneIdleConnection())
return true;
}
@@ -1142,7 +1179,7 @@
while (IsStalled()) {
// Closing a socket will result in calling back into |this| to use the freed
// socket slot, so nothing else is needed.
- if (!CloseOneIdleConnectionInLayeredPool())
+ if (!CloseOneIdleConnectionInHigherLayeredPool())
return;
}
}

Powered by Google App Engine
This is Rietveld 408576698