Commit 3aa054ce authored by willchan@chromium.org's avatar willchan@chromium.org

Only create the backup ConnectJob when it is needed.

This reduces the unnecessary NetLog spam, since we would log to the NetLog everytime we created the backup ConnectJob, even though we usually wouldn't actually call Connect() on it.  Now, we only create the backup ConnectJob when we intend to call Connect() on it.
Includes some various cleanup necessary for this:
  * struct Group => class Group
  * method_factory moves from CSP to Group

Review URL: http://codereview.chromium.org/3171017

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@57100 0039d316-1c4b-4281-b951-d872f2087c98
parent 4bca888c
This diff is collapsed.
...@@ -228,7 +228,7 @@ class ClientSocketPoolBaseHelper ...@@ -228,7 +228,7 @@ class ClientSocketPoolBaseHelper
virtual void OnIPAddressChanged(); virtual void OnIPAddressChanged();
int NumConnectJobsInGroup(const std::string& group_name) const { 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 // Closes all idle sockets if |force| is true. Else, only closes idle
...@@ -268,57 +268,69 @@ class ClientSocketPoolBaseHelper ...@@ -268,57 +268,69 @@ class ClientSocketPoolBaseHelper
// A Group is allocated per group_name when there are idle sockets or pending // A Group is allocated per group_name when there are idle sockets or pending
// requests. Otherwise, the Group object is removed from the map. // requests. Otherwise, the Group object is removed from the map.
// |active_socket_count| tracks the number of sockets held by clients. // |active_socket_count| tracks the number of sockets held by clients.
struct Group { class Group {
Group() public:
: active_socket_count(0), Group();
backup_job(NULL), ~Group();
backup_task(NULL) {
}
~Group() {
CleanupBackupJob();
}
bool IsEmpty() const { bool IsEmpty() const {
return active_socket_count == 0 && idle_sockets.empty() && jobs.empty() && return active_socket_count_ == 0 && idle_sockets_.empty() &&
pending_requests.empty(); jobs_.empty() && pending_requests_.empty();
} }
bool HasAvailableSocketSlot(int max_sockets_per_group) const { 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; max_sockets_per_group;
} }
bool IsStalled(int max_sockets_per_group) const { bool IsStalled(int max_sockets_per_group) const {
return HasAvailableSocketSlot(max_sockets_per_group) && return HasAvailableSocketSlot(max_sockets_per_group) &&
pending_requests.size() > jobs.size(); pending_requests_.size() > jobs_.size();
} }
RequestPriority TopPendingPriority() const { RequestPriority TopPendingPriority() const {
return pending_requests.front()->priority(); return pending_requests_.front()->priority();
} }
bool HasBackupJob() const { return !method_factory_.empty(); }
void CleanupBackupJob() { void CleanupBackupJob() {
if (backup_job) { method_factory_.RevokeAll();
delete backup_job;
backup_job = NULL;
}
if (backup_task) {
backup_task->Cancel();
backup_task = NULL;
}
} }
std::deque<IdleSocket> idle_sockets; // Set a timer to create a backup socket if it takes too long to create one.
std::set<const ConnectJob*> jobs; void StartBackupSocketTimer(const std::string& group_name,
RequestQueue pending_requests; ClientSocketPoolBaseHelper* pool);
int active_socket_count; // number of active sockets used by clients
// A backup job in case the connect for this group takes too long. // Called when the backup socket timer fires.
ConnectJob* backup_job; void OnBackupSocketTimerFired(
CancelableTask* backup_task; 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_;
}; };
typedef std::map<std::string, Group> GroupMap; typedef std::map<std::string, Group*> GroupMap;
typedef std::set<const ConnectJob*> ConnectJobSet; typedef std::set<const ConnectJob*> ConnectJobSet;
...@@ -341,6 +353,10 @@ class ClientSocketPoolBaseHelper ...@@ -341,6 +353,10 @@ class ClientSocketPoolBaseHelper
static const Request* RemoveRequestFromQueue(RequestQueue::iterator it, static const Request* RemoveRequestFromQueue(RequestQueue::iterator it,
RequestQueue* pending_requests); 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. // Called when the number of idle sockets changes.
void IncrementIdleCount(); void IncrementIdleCount();
void DecrementIdleCount(); void DecrementIdleCount();
...@@ -394,17 +410,11 @@ class ClientSocketPoolBaseHelper ...@@ -394,17 +410,11 @@ class ClientSocketPoolBaseHelper
// Assigns an idle socket for the group to the request. // Assigns an idle socket for the group to the request.
// Returns |true| if an idle socket is available, false otherwise. // Returns |true| if an idle socket is available, false otherwise.
bool AssignIdleSocketToGroup(Group* group, const Request* request); bool AssignIdleSocketToGroup(const Request* request, Group* group);
static void LogBoundConnectJobToRequest( static void LogBoundConnectJobToRequest(
const NetLog::Source& connect_job_source, const Request* request); 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. // Closes one idle socket. Picks the first one encountered.
// TODO(willchan): Consider a better algorithm for doing this. Perhaps we // TODO(willchan): Consider a better algorithm for doing this. Perhaps we
// should keep an ordered list of idle sockets, and close them in order. // should keep an ordered list of idle sockets, and close them in order.
...@@ -463,9 +473,6 @@ class ClientSocketPoolBaseHelper ...@@ -463,9 +473,6 @@ class ClientSocketPoolBaseHelper
// TODO(vandebo) Remove when backup jobs move to TCPClientSocketPool // TODO(vandebo) Remove when backup jobs move to TCPClientSocketPool
bool backup_jobs_enabled_; 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 // 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 // pool. This is so that when sockets get released back to the pool, we can
// make sure that they are discarded rather than reused. // make sure that they are discarded rather than reused.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment