diff options
Diffstat (limited to 'net/socket')
-rw-r--r-- | net/socket/client_socket_pool_base.cc | 312 | ||||
-rw-r--r-- | net/socket/client_socket_pool_base.h | 91 |
2 files changed, 188 insertions, 215 deletions
diff --git a/net/socket/client_socket_pool_base.cc b/net/socket/client_socket_pool_base.cc index c239c69..334a9dc 100644 --- a/net/socket/client_socket_pool_base.cc +++ b/net/socket/client_socket_pool_base.cc @@ -138,6 +138,7 @@ ClientSocketPoolBaseHelper::ClientSocketPoolBaseHelper( 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 @@ int ClientSocketPoolBaseHelper::RequestSocket( 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 @@ int ClientSocketPoolBaseHelper::RequestSocket( 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 @@ int ClientSocketPoolBaseHelper::RequestSocketInternal( 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 @@ int ClientSocketPoolBaseHelper::RequestSocketInternal( 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 @@ int ClientSocketPoolBaseHelper::RequestSocketInternal( } 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 @@ void ClientSocketPoolBaseHelper::LogBoundConnectJobToRequest( 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 @@ void ClientSocketPoolBaseHelper::CancelRequest( 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 @@ int ClientSocketPoolBaseHelper::IdleSocketCountInGroup( 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 @@ LoadState ClientSocketPoolBaseHelper::GetLoadState( } // 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 @@ void ClientSocketPoolBaseHelper::CleanupIdleSockets(bool force) { 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 @@ void ClientSocketPoolBaseHelper::CleanupIdleSockets(bool force) { } // 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 @@ void ClientSocketPoolBaseHelper::ReleaseSocket(const std::string& group_name, 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 ClientSocketPoolBaseHelper::FindTopStalledGroup(Group** group, 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 @@ void ClientSocketPoolBaseHelper::OnConnectJobComplete( 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 @@ void ClientSocketPoolBaseHelper::OnConnectJobComplete( 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 @@ void ClientSocketPoolBaseHelper::RemoveConnectJob(const ConnectJob* job, 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::RemoveConnectJob(const ConnectJob* job, 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 @@ void ClientSocketPoolBaseHelper::HandOutSocket( "source_dependency", socket->NetLog().source())); handed_out_socket_count_++; - group->IncrementActiveSocketCount(); + group->active_socket_count++; } void ClientSocketPoolBaseHelper::AddIdleSocket( @@ -702,19 +736,26 @@ void ClientSocketPoolBaseHelper::AddIdleSocket( 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 @@ void ClientSocketPoolBaseHelper::CloseOneIdleSocket() { 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 @@ void ClientSocketPoolBaseHelper::InvokeUserCallback( 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 diff --git a/net/socket/client_socket_pool_base.h b/net/socket/client_socket_pool_base.h index 33f8072..96c78d5 100644 --- a/net/socket/client_socket_pool_base.h +++ b/net/socket/client_socket_pool_base.h @@ -228,7 +228,7 @@ class ClientSocketPoolBaseHelper virtual void OnIPAddressChanged(); int NumConnectJobsInGroup(const std::string& group_name) const { - return group_map_.find(group_name)->second->jobs().size(); + return group_map_.find(group_name)->second.jobs.size(); } // Closes all idle sockets if |force| is true. Else, only closes idle @@ -268,69 +268,57 @@ class ClientSocketPoolBaseHelper // A Group is allocated per group_name when there are idle sockets or pending // requests. Otherwise, the Group object is removed from the map. // |active_socket_count| tracks the number of sockets held by clients. - class Group { - public: - Group(); - ~Group(); + struct Group { + Group() + : active_socket_count(0), + backup_job(NULL), + backup_task(NULL) { + } + + ~Group() { + CleanupBackupJob(); + } bool IsEmpty() const { - return active_socket_count_ == 0 && idle_sockets_.empty() && - jobs_.empty() && pending_requests_.empty(); + return active_socket_count == 0 && idle_sockets.empty() && jobs.empty() && + pending_requests.empty(); } bool HasAvailableSocketSlot(int max_sockets_per_group) const { - return active_socket_count_ + static_cast<int>(jobs_.size()) < + return active_socket_count + static_cast<int>(jobs.size()) < max_sockets_per_group; } bool IsStalled(int max_sockets_per_group) const { return HasAvailableSocketSlot(max_sockets_per_group) && - pending_requests_.size() > jobs_.size(); + pending_requests.size() > jobs.size(); } RequestPriority TopPendingPriority() const { - return pending_requests_.front()->priority(); + return pending_requests.front()->priority(); } - bool HasBackupJob() const { return !method_factory_.empty(); } - void CleanupBackupJob() { - method_factory_.RevokeAll(); + if (backup_job) { + delete backup_job; + backup_job = NULL; + } + if (backup_task) { + backup_task->Cancel(); + backup_task = NULL; + } } - // Set a timer to create a backup socket if it takes too long to create one. - void StartBackupSocketTimer(const std::string& group_name, - ClientSocketPoolBaseHelper* pool); - - // Called when the backup socket timer fires. - void OnBackupSocketTimerFired( - std::string group_name, - ClientSocketPoolBaseHelper* pool); - - void AddJob(const ConnectJob* job) { jobs_.insert(job); } - void RemoveJob(const ConnectJob* job) { jobs_.erase(job); } - void RemoveAllJobs(); - - void IncrementActiveSocketCount() { active_socket_count_++; } - void DecrementActiveSocketCount() { active_socket_count_--; } - - const std::set<const ConnectJob*>& jobs() const { return jobs_; } - const std::deque<IdleSocket>& idle_sockets() const { return idle_sockets_; } - const RequestQueue& pending_requests() const { return pending_requests_; } - int active_socket_count() const { return active_socket_count_; } - RequestQueue* mutable_pending_requests() { return &pending_requests_; } - std::deque<IdleSocket>* mutable_idle_sockets() { return &idle_sockets_; } - - private: - std::deque<IdleSocket> idle_sockets_; - std::set<const ConnectJob*> jobs_; - RequestQueue pending_requests_; - int active_socket_count_; // number of active sockets used by clients - // A factory to pin the backup_job tasks. - ScopedRunnableMethodFactory<Group> method_factory_; + std::deque<IdleSocket> idle_sockets; + std::set<const ConnectJob*> jobs; + RequestQueue pending_requests; + int active_socket_count; // number of active sockets used by clients + // A backup job in case the connect for this group takes too long. + ConnectJob* backup_job; + CancelableTask* backup_task; }; - typedef std::map<std::string, Group*> GroupMap; + typedef std::map<std::string, Group> GroupMap; typedef std::set<const ConnectJob*> ConnectJobSet; @@ -353,10 +341,6 @@ class ClientSocketPoolBaseHelper static const Request* RemoveRequestFromQueue(RequestQueue::iterator it, RequestQueue* pending_requests); - Group* GetOrCreateGroup(const std::string& group_name); - void RemoveGroup(const std::string& group_name); - void RemoveGroup(GroupMap::iterator it); - // Called when the number of idle sockets changes. void IncrementIdleCount(); void DecrementIdleCount(); @@ -410,11 +394,17 @@ class ClientSocketPoolBaseHelper // Assigns an idle socket for the group to the request. // Returns |true| if an idle socket is available, false otherwise. - bool AssignIdleSocketToGroup(const Request* request, Group* group); + bool AssignIdleSocketToGroup(Group* group, const Request* request); static void LogBoundConnectJobToRequest( const NetLog::Source& connect_job_source, const Request* request); + // Set a timer to create a backup socket if it takes too long to create one. + void StartBackupSocketTimer(const std::string& group_name); + + // Called when the backup socket timer fires. + void OnBackupSocketTimerFired(const std::string& group_name); + // Closes one idle socket. Picks the first one encountered. // TODO(willchan): Consider a better algorithm for doing this. Perhaps we // should keep an ordered list of idle sockets, and close them in order. @@ -473,6 +463,9 @@ class ClientSocketPoolBaseHelper // TODO(vandebo) Remove when backup jobs move to TCPClientSocketPool bool backup_jobs_enabled_; + // A factory to pin the backup_job tasks. + ScopedRunnableMethodFactory<ClientSocketPoolBaseHelper> method_factory_; + // A unique id for the pool. It gets incremented every time we Flush() the // pool. This is so that when sockets get released back to the pool, we can // make sure that they are discarded rather than reused. |