summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorkristianm@chromium.org <kristianm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-08 04:22:28 +0000
committerkristianm@chromium.org <kristianm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-08 04:22:28 +0000
commit4a3315aa161157d999188daed1d276f49c3867bc (patch)
tree056a75deef784f5df3e3d6eb28d3a5bf6a8e20e1 /net
parent83f366259f43e3a11b1dfff40df768dadef6b6f8 (diff)
downloadchromium_src-4a3315aa161157d999188daed1d276f49c3867bc.zip
chromium_src-4a3315aa161157d999188daed1d276f49c3867bc.tar.gz
chromium_src-4a3315aa161157d999188daed1d276f49c3867bc.tar.bz2
Exposing CloseIdleConnections in HttpCache, and close idle spdy sessions
Adding CloseIdleSessions to SPDY, use it when closing idle sessions in HttpNetworkSession. Expose CloseIdleConnections to HttpCache so it can be use when from clients of the HttpCache. BUG=None TEST=None Review URL: http://codereview.chromium.org/7380004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@100100 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r--net/http/http_cache.cc8
-rw-r--r--net/http/http_cache.h3
-rw-r--r--net/http/http_network_session.cc1
-rw-r--r--net/spdy/spdy_session.h5
-rw-r--r--net/spdy/spdy_session_pool.cc16
-rw-r--r--net/spdy/spdy_session_pool.h2
-rw-r--r--net/spdy/spdy_session_unittest.cc106
7 files changed, 141 insertions, 0 deletions
diff --git a/net/http/http_cache.cc b/net/http/http_cache.cc
index 589777d..738a539 100644
--- a/net/http/http_cache.cc
+++ b/net/http/http_cache.cc
@@ -465,6 +465,14 @@ void HttpCache::CloseAllConnections() {
HttpNetworkSession* session = network->GetSession();
if (session)
session->CloseAllConnections();
+ }
+
+void HttpCache::CloseIdleConnections() {
+ net::HttpNetworkLayer* network =
+ static_cast<net::HttpNetworkLayer*>(network_layer_.get());
+ HttpNetworkSession* session = network->GetSession();
+ if (session)
+ session->CloseIdleConnections();
}
void HttpCache::OnExternalCacheHit(const GURL& url,
diff --git a/net/http/http_cache.h b/net/http/http_cache.h
index 5e29701..e9f0e11 100644
--- a/net/http/http_cache.h
+++ b/net/http/http_cache.h
@@ -181,6 +181,9 @@ class NET_EXPORT HttpCache : public HttpTransactionFactory,
// immediately, but they will not be reusable. This is for debugging.
void CloseAllConnections();
+ // Close all idle connections. Will close all sockets not in active use.
+ void CloseIdleConnections();
+
// Called whenever an external cache in the system reuses the resource
// referred to by |url| and |http_method|.
void OnExternalCacheHit(const GURL& url, const std::string& http_method);
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc
index b52aa107..b5a104d 100644
--- a/net/http/http_network_session.cc
+++ b/net/http/http_network_session.cc
@@ -94,6 +94,7 @@ void HttpNetworkSession::CloseAllConnections() {
void HttpNetworkSession::CloseIdleConnections() {
socket_pool_manager_.CloseIdleSockets();
+ spdy_session_pool_.CloseIdleSessions();
}
} // namespace net
diff --git a/net/spdy/spdy_session.h b/net/spdy/spdy_session.h
index 4281a20..1a038f8 100644
--- a/net/spdy/spdy_session.h
+++ b/net/spdy/spdy_session.h
@@ -190,6 +190,11 @@ class NET_EXPORT SpdySession : public base::RefCounted<SpdySession>,
spdy_session_pool_ = NULL;
}
+ // Returns true if session is not currently active
+ bool is_active() const {
+ return !active_streams_.empty();
+ }
+
// Access to the number of active and pending streams. These are primarily
// available for testing and diagnostics.
size_t num_active_streams() const { return active_streams_.size(); }
diff --git a/net/spdy/spdy_session_pool.cc b/net/spdy/spdy_session_pool.cc
index d90a1d5..7bac3bc 100644
--- a/net/spdy/spdy_session_pool.cc
+++ b/net/spdy/spdy_session_pool.cc
@@ -413,4 +413,20 @@ void SpdySessionPool::CloseCurrentSessions() {
DCHECK(aliases_.empty());
}
+void SpdySessionPool::CloseIdleSessions() {
+ SpdySessionsMap::const_iterator map_it = sessions_.begin();
+ while (map_it != sessions_.end()) {
+ SpdySessionList* list = map_it->second;
+ ++map_it;
+ CHECK(list);
+
+ // Assumes there is only 1 element in the list
+ SpdySessionList::iterator session_it = list->begin();
+ const scoped_refptr<SpdySession>& session = *session_it;
+ CHECK(session);
+ if (!session->is_active())
+ session->CloseSessionOnError(net::ERR_ABORTED, true);
+ }
+}
+
} // namespace net
diff --git a/net/spdy/spdy_session_pool.h b/net/spdy/spdy_session_pool.h
index 327e179..3b1ec78 100644
--- a/net/spdy/spdy_session_pool.h
+++ b/net/spdy/spdy_session_pool.h
@@ -92,6 +92,8 @@ class NET_EXPORT SpdySessionPool
// Close only the currently existing SpdySessions. Let any new ones created
// continue to live.
void CloseCurrentSessions();
+ // Close only the idle SpdySessions.
+ void CloseIdleSessions();
// Removes a SpdySession from the SpdySessionPool. This should only be called
// by SpdySession, because otherwise session->state_ is not set to CLOSED.
diff --git a/net/spdy/spdy_session_unittest.cc b/net/spdy/spdy_session_unittest.cc
index 351b8ed..9a0a2be 100644
--- a/net/spdy/spdy_session_unittest.cc
+++ b/net/spdy/spdy_session_unittest.cc
@@ -150,6 +150,112 @@ class StreamReleaserCallback : public CallbackRunner<Tuple1<int> > {
TestCompletionCallback callback_;
};
+// TODO(kristianm): Could also test with more sessions where some are idle,
+// and more than one session to a HostPortPair.
+TEST_F(SpdySessionTest, CloseIdleSessions) {
+ SpdySessionDependencies session_deps;
+ scoped_refptr<HttpNetworkSession> http_session(
+ SpdySessionDependencies::SpdyCreateSession(&session_deps));
+ SpdySessionPool* spdy_session_pool(http_session->spdy_session_pool());
+
+ // Set up session 1
+ const std::string kTestHost1("http://www.a.com");
+ HostPortPair test_host_port_pair1(kTestHost1, 80);
+ HostPortProxyPair pair1(test_host_port_pair1, ProxyServer::Direct());
+ scoped_refptr<SpdySession> session1 =
+ spdy_session_pool->Get(pair1, BoundNetLog());
+ scoped_refptr<SpdyStream> spdy_stream1;
+ TestCompletionCallback callback1;
+ GURL url1(kTestHost1);
+ EXPECT_EQ(OK, session1->CreateStream(url1,
+ MEDIUM, /* priority, not important */
+ &spdy_stream1,
+ BoundNetLog(),
+ &callback1));
+
+ // Set up session 2
+ const std::string kTestHost2("http://www.b.com");
+ HostPortPair test_host_port_pair2(kTestHost2, 80);
+ HostPortProxyPair pair2(test_host_port_pair2, ProxyServer::Direct());
+ scoped_refptr<SpdySession> session2 =
+ spdy_session_pool->Get(pair2, BoundNetLog());
+ scoped_refptr<SpdyStream> spdy_stream2;
+ TestCompletionCallback callback2;
+ GURL url2(kTestHost2);
+ EXPECT_EQ(OK, session2->CreateStream(url2,
+ MEDIUM, /* priority, not important */
+ &spdy_stream2,
+ BoundNetLog(),
+ &callback2));
+
+ // Set up session 3
+ const std::string kTestHost3("http://www.c.com");
+ HostPortPair test_host_port_pair3(kTestHost3, 80);
+ HostPortProxyPair pair3(test_host_port_pair3, ProxyServer::Direct());
+ scoped_refptr<SpdySession> session3 =
+ spdy_session_pool->Get(pair3, BoundNetLog());
+ scoped_refptr<SpdyStream> spdy_stream3;
+ TestCompletionCallback callback3;
+ GURL url3(kTestHost3);
+ EXPECT_EQ(OK, session3->CreateStream(url3,
+ MEDIUM, /* priority, not important */
+ &spdy_stream3,
+ BoundNetLog(),
+ &callback3));
+
+ // All sessions are active and not closed
+ EXPECT_TRUE(session1->is_active());
+ EXPECT_FALSE(session1->IsClosed());
+ EXPECT_TRUE(session2->is_active());
+ EXPECT_FALSE(session2->IsClosed());
+ EXPECT_TRUE(session3->is_active());
+ EXPECT_FALSE(session3->IsClosed());
+
+ // Should not do anything, all are active
+ spdy_session_pool->CloseIdleSessions();
+ EXPECT_TRUE(session1->is_active());
+ EXPECT_FALSE(session1->IsClosed());
+ EXPECT_TRUE(session2->is_active());
+ EXPECT_FALSE(session2->IsClosed());
+ EXPECT_TRUE(session3->is_active());
+ EXPECT_FALSE(session3->IsClosed());
+
+ // Make sessions 1 and 3 inactive, but keep them open.
+ // Session 2 still open and active
+ session1->CloseStream(spdy_stream1->stream_id(), OK);
+ session3->CloseStream(spdy_stream3->stream_id(), OK);
+ EXPECT_FALSE(session1->is_active());
+ EXPECT_FALSE(session1->IsClosed());
+ EXPECT_TRUE(session2->is_active());
+ EXPECT_FALSE(session2->IsClosed());
+ EXPECT_FALSE(session3->is_active());
+ EXPECT_FALSE(session3->IsClosed());
+
+ // Should close session 1 and 3, 2 should be left open
+ spdy_session_pool->CloseIdleSessions();
+ EXPECT_FALSE(session1->is_active());
+ EXPECT_TRUE(session1->IsClosed());
+ EXPECT_TRUE(session2->is_active());
+ EXPECT_FALSE(session2->IsClosed());
+ EXPECT_FALSE(session3->is_active());
+ EXPECT_TRUE(session3->IsClosed());
+
+ // Should not do anything
+ spdy_session_pool->CloseIdleSessions();
+ EXPECT_TRUE(session2->is_active());
+ EXPECT_FALSE(session2->IsClosed());
+
+ // Make 2 not active
+ session2->CloseStream(spdy_stream2->stream_id(), OK);
+ EXPECT_FALSE(session2->is_active());
+ EXPECT_FALSE(session2->IsClosed());
+
+ // This should close session 2
+ spdy_session_pool->CloseIdleSessions();
+ EXPECT_FALSE(session2->is_active());
+ EXPECT_TRUE(session2->IsClosed());
+}
+
// Start with max concurrent streams set to 1. Request two streams. Receive a
// settings frame setting max concurrent streams to 2. Have the callback
// release the stream, which releases its reference (the last) to the session.