summaryrefslogtreecommitdiffstats
path: root/net/socket/client_socket_pool_base.cc
diff options
context:
space:
mode:
authorwillchan@chromium.org <willchan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-13 00:55:03 +0000
committerwillchan@chromium.org <willchan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-13 00:55:03 +0000
commit2c2bef15bfeea057bfd7f0c1c5ae1244ae4ed03d (patch)
tree23b324be2991afa9da65a4597cc3fb1baef5bd8c /net/socket/client_socket_pool_base.cc
parentf04f73aa57b809af0e047048b88abe02b8012554 (diff)
downloadchromium_src-2c2bef15bfeea057bfd7f0c1c5ae1244ae4ed03d.zip
chromium_src-2c2bef15bfeea057bfd7f0c1c5ae1244ae4ed03d.tar.gz
chromium_src-2c2bef15bfeea057bfd7f0c1c5ae1244ae4ed03d.tar.bz2
Add ClientSocketPoolBaseHelper support for preconnect.
Adds a RequestSockets() API to ClientSocketPool interface. - no RequestPriority param, all requests default to LOWEST. - adds a |num_sockets| param to control how many sockets to try to ensure are connected. Adds an implementation for said function in ClientSocketPoolBaseHelper. Adds a new ClientSocketPoolBaseHelper::Flag type to modify socket request behavior. In this case, we bypass idle sockets. Adds a preconnect concept to ConnectJob. This lets normal requests hijack preconnect jobs. Modifies all ClientSocketPool subclasses to support new RequestSockets API(). Adds new tests. No client actually uses this API yet. We need to plumb it up to the preconnect system. BUG=54450 TEST=new tests in ClientSocketPoolBaseTest Review URL: http://codereview.chromium.org/3689004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@62365 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/socket/client_socket_pool_base.cc')
-rw-r--r--net/socket/client_socket_pool_base.cc107
1 files changed, 90 insertions, 17 deletions
diff --git a/net/socket/client_socket_pool_base.cc b/net/socket/client_socket_pool_base.cc
index 994e1d2..13d8b68 100644
--- a/net/socket/client_socket_pool_base.cc
+++ b/net/socket/client_socket_pool_base.cc
@@ -44,7 +44,8 @@ ConnectJob::ConnectJob(const std::string& group_name,
timeout_duration_(timeout_duration),
delegate_(delegate),
net_log_(net_log),
- idle_(true) {
+ idle_(true),
+ preconnect_state_(NOT_PRECONNECT) {
DCHECK(!group_name.empty());
DCHECK(delegate);
net_log.BeginEvent(NetLog::TYPE_SOCKET_POOL_CONNECT_JOB, NULL);
@@ -54,6 +55,13 @@ ConnectJob::~ConnectJob() {
net_log().EndEvent(NetLog::TYPE_SOCKET_POOL_CONNECT_JOB, NULL);
}
+void ConnectJob::Initialize(bool is_preconnect) {
+ if (is_preconnect)
+ preconnect_state_ = UNUSED_PRECONNECT;
+ else
+ preconnect_state_ = NOT_PRECONNECT;
+}
+
int ConnectJob::Connect() {
if (timeout_duration_ != base::TimeDelta())
timer_.Start(timeout_duration_, this, &ConnectJob::OnTimeout);
@@ -72,6 +80,11 @@ int ConnectJob::Connect() {
return rv;
}
+void ConnectJob::UseForNormalRequest() {
+ DCHECK_EQ(UNUSED_PRECONNECT, preconnect_state_);
+ preconnect_state_ = USED_PRECONNECT;
+}
+
void ConnectJob::set_socket(ClientSocket* socket) {
if (socket) {
net_log().AddEvent(NetLog::TYPE_CONNECT_JOB_SET_SOCKET,
@@ -122,10 +135,12 @@ ClientSocketPoolBaseHelper::Request::Request(
ClientSocketHandle* handle,
CompletionCallback* callback,
RequestPriority priority,
+ Flags flags,
const BoundNetLog& net_log)
: handle_(handle),
callback_(callback),
priority_(priority),
+ flags_(flags),
net_log_(net_log) {}
ClientSocketPoolBaseHelper::Request::~Request() {}
@@ -193,6 +208,9 @@ ClientSocketPoolBaseHelper::RemoveRequestFromQueue(
int ClientSocketPoolBaseHelper::RequestSocket(
const std::string& group_name,
const Request* request) {
+ CHECK(request->callback());
+ CHECK(request->handle());
+
request->net_log().BeginEvent(NetLog::TYPE_SOCKET_POOL, NULL);
Group* group = GetOrCreateGroup(group_name);
@@ -207,19 +225,57 @@ int ClientSocketPoolBaseHelper::RequestSocket(
return rv;
}
+void ClientSocketPoolBaseHelper::RequestSockets(
+ const std::string& group_name,
+ const Request& request,
+ int num_sockets) {
+ DCHECK(!request.callback());
+ DCHECK(!request.handle());
+
+ if (num_sockets > max_sockets_per_group_) {
+ NOTREACHED();
+ num_sockets = max_sockets_per_group_;
+ }
+
+ request.net_log().BeginEvent(
+ NetLog::TYPE_SOCKET_POOL_CONNECTING_N_SOCKETS,
+ new NetLogIntegerParameter("num_sockets", num_sockets));
+
+ Group* group = GetOrCreateGroup(group_name);
+
+ for (int num_iterations_left = num_sockets;
+ group->NumActiveSocketSlots() < num_sockets &&
+ num_iterations_left > 0 ; num_iterations_left--) {
+ int rv = RequestSocketInternal(group_name, &request);
+ if (rv < 0 && rv != ERR_IO_PENDING) {
+ // We're encountering a synchronous error. Give up.
+ break;
+ }
+ }
+
+ if (group->IsEmpty())
+ RemoveGroup(group_name);
+
+ request.net_log().EndEvent(
+ NetLog::TYPE_SOCKET_POOL_CONNECTING_N_SOCKETS, NULL);
+}
+
int ClientSocketPoolBaseHelper::RequestSocketInternal(
const std::string& group_name,
const Request* request) {
DCHECK_GE(request->priority(), 0);
- CompletionCallback* const callback = request->callback();
- CHECK(callback);
ClientSocketHandle* const handle = request->handle();
- CHECK(handle);
+ const bool preconnecting = !handle;
Group* group = GetOrCreateGroup(group_name);
- // Try to reuse a socket.
- if (AssignIdleSocketToGroup(request, group))
- return OK;
+ if (!(request->flags() & NO_IDLE_SOCKETS)) {
+ // Try to reuse a socket.
+ if (AssignIdleSocketToGroup(request, group))
+ return OK;
+ }
+
+ if (!preconnecting && group->TryToUsePreconnectConnectJob())
+ return ERR_IO_PENDING;
// Can we make another active socket now?
if (!group->HasAvailableSocketSlot(max_sockets_per_group_)) {
@@ -244,18 +300,25 @@ int ClientSocketPoolBaseHelper::RequestSocketInternal(
scoped_ptr<ConnectJob> connect_job(
connect_job_factory_->NewConnectJob(group_name, *request, this));
+ connect_job->Initialize(preconnecting);
int rv = connect_job->Connect();
if (rv == OK) {
LogBoundConnectJobToRequest(connect_job->net_log().source(), request);
- HandOutSocket(connect_job->ReleaseSocket(), false /* not reused */,
- handle, base::TimeDelta(), group, request->net_log());
+ if (!preconnecting) {
+ HandOutSocket(connect_job->ReleaseSocket(), false /* not reused */,
+ handle, base::TimeDelta(), group, request->net_log());
+ } else {
+ AddIdleSocket(connect_job->ReleaseSocket(), group);
+ }
} 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() &&
- connect_backup_jobs_enabled_)
+ if (connect_backup_jobs_enabled_ &&
+ group->IsEmpty() && !group->HasBackupJob() &&
+ handle) {
group->StartBackupSocketTimer(group_name, this);
+ }
connecting_socket_count_++;
@@ -357,10 +420,9 @@ void ClientSocketPoolBaseHelper::CancelRequest(
RequestQueue::iterator it = group->mutable_pending_requests()->begin();
for (; it != group->pending_requests().end(); ++it) {
if ((*it)->handle() == handle) {
- const Request* req = RemoveRequestFromQueue(it, group);
+ scoped_ptr<const Request> req(RemoveRequestFromQueue(it, group));
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()) {
@@ -468,7 +530,7 @@ DictionaryValue* ClientSocketPoolBaseHelper::GetInfoAsValue(
group_dict->Set("idle_sockets", idle_socket_list);
ListValue* connect_jobs_list = new ListValue();
- std::set<const ConnectJob*>::const_iterator job = group->jobs().begin();
+ std::set<ConnectJob*>::const_iterator job = group->jobs().begin();
for (job = group->jobs().begin(); job != group->jobs().end(); job++) {
int source_id = (*job)->net_log().source().id;
connect_jobs_list->Append(Value::CreateIntegerValue(source_id));
@@ -725,7 +787,7 @@ void ClientSocketPoolBaseHelper::Flush() {
AbortAllRequests();
}
-void ClientSocketPoolBaseHelper::RemoveConnectJob(const ConnectJob* job,
+void ClientSocketPoolBaseHelper::RemoveConnectJob(ConnectJob* job,
Group* group) {
CHECK_GT(connecting_socket_count_, 0);
connecting_socket_count_--;
@@ -837,10 +899,9 @@ void ClientSocketPoolBaseHelper::AbortAllRequests() {
pending_requests.swap(*group->mutable_pending_requests());
for (RequestQueue::iterator it2 = pending_requests.begin();
it2 != pending_requests.end(); ++it2) {
- const Request* request = *it2;
+ scoped_ptr<const Request> request(*it2);
InvokeUserCallbackLater(
request->handle(), request->callback(), ERR_ABORTED);
- delete request;
}
// Delete group if no longer needed.
@@ -934,6 +995,18 @@ void ClientSocketPoolBaseHelper::Group::StartBackupSocketTimer(
pool->ConnectRetryIntervalMs());
}
+bool ClientSocketPoolBaseHelper::Group::TryToUsePreconnectConnectJob() {
+ for (std::set<ConnectJob*>::iterator it = jobs_.begin();
+ it != jobs_.end(); ++it) {
+ ConnectJob* job = *it;
+ if (job->is_unused_preconnect()) {
+ job->UseForNormalRequest();
+ return true;
+ }
+ }
+ return false;
+}
+
void ClientSocketPoolBaseHelper::Group::OnBackupSocketTimerFired(
std::string group_name,
ClientSocketPoolBaseHelper* pool) {