| Index: net/socket/client_socket_pool_base.cc
|
| diff --git a/net/socket/client_socket_pool_base.cc b/net/socket/client_socket_pool_base.cc
|
| index 123c3cfde7499d8c2ad9ed35687b56cacceaf7f7..56eb1ab7a81f98495b559fd6935573ff509374dc 100644
|
| --- a/net/socket/client_socket_pool_base.cc
|
| +++ b/net/socket/client_socket_pool_base.cc
|
| @@ -30,6 +30,20 @@ const int kIdleTimeout = 300; // 5 minutes.
|
|
|
| namespace net {
|
|
|
| +ConnectJob::ConnectJob(const std::string& group_name,
|
| + const ClientSocketHandle* key_handle,
|
| + Delegate* delegate)
|
| + : group_name_(group_name),
|
| + key_handle_(key_handle),
|
| + delegate_(delegate),
|
| + load_state_(LOAD_STATE_IDLE) {
|
| + DCHECK(!group_name.empty());
|
| + DCHECK(key_handle);
|
| + DCHECK(delegate);
|
| +}
|
| +
|
| +ConnectJob::~ConnectJob() {}
|
| +
|
| ClientSocketPoolBase::ClientSocketPoolBase(
|
| int max_sockets_per_group,
|
| ConnectJobFactory* connect_job_factory)
|
| @@ -70,29 +84,21 @@ int ClientSocketPoolBase::RequestSocket(
|
| DCHECK(callback);
|
| Group& group = group_map_[group_name];
|
|
|
| - CheckSocketCounts(group);
|
| -
|
| // Can we make another active socket now?
|
| - if (group.active_socket_count == max_sockets_per_group_) {
|
| + if (!group.HasAvailableSocketSlot(max_sockets_per_group_)) {
|
| CHECK(callback);
|
| Request r(handle, callback, priority, resolve_info);
|
| InsertRequestIntoQueue(r, &group.pending_requests);
|
| return ERR_IO_PENDING;
|
| }
|
|
|
| - // OK, we are going to activate one.
|
| - group.active_socket_count++;
|
| -
|
| 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!
|
| - handle->set_socket(idle_socket.socket);
|
| - handle->set_is_reused(true);
|
| - group.sockets_handed_out_count++;
|
| - CheckSocketCounts(group);
|
| + HandOutSocket(idle_socket.socket, true /* reuse */, handle, &group);
|
| return OK;
|
| }
|
| delete idle_socket.socket;
|
| @@ -102,14 +108,23 @@ int ClientSocketPoolBase::RequestSocket(
|
|
|
| CHECK(callback);
|
| Request r(handle, callback, priority, resolve_info);
|
| - group.connecting_requests[handle] = r;
|
| -
|
| - CHECK(!ContainsKey(connect_job_map_, handle));
|
| + scoped_ptr<ConnectJob> connect_job(
|
| + connect_job_factory_->NewConnectJob(group_name, r, this));
|
| +
|
| + int rv = connect_job->Connect();
|
| + if (rv == OK) {
|
| + HandOutSocket(connect_job->ReleaseSocket(), false /* not reused */,
|
| + handle, &group);
|
| + } else if (rv == ERR_IO_PENDING) {
|
| + group.connecting_requests[handle] = r;
|
| + CHECK(!ContainsKey(connect_job_map_, handle));
|
| + connect_job_map_[handle] = connect_job.release();
|
| + } else {
|
| + if (group.IsEmpty())
|
| + group_map_.erase(group_name);
|
| + }
|
|
|
| - ConnectJob* connect_job =
|
| - connect_job_factory_->NewConnectJob(group_name, r, this);
|
| - connect_job_map_[handle] = connect_job;
|
| - return connect_job->Connect();
|
| + return rv;
|
| }
|
|
|
| void ClientSocketPoolBase::CancelRequest(const std::string& group_name,
|
| @@ -118,8 +133,6 @@ void ClientSocketPoolBase::CancelRequest(const std::string& group_name,
|
|
|
| Group& group = group_map_[group_name];
|
|
|
| - CheckSocketCounts(group);
|
| -
|
| // Search pending_requests for matching handle.
|
| RequestQueue::iterator it = group.pending_requests.begin();
|
| for (; it != group.pending_requests.end(); ++it) {
|
| @@ -136,7 +149,7 @@ void ClientSocketPoolBase::CancelRequest(const std::string& group_name,
|
| if (map_it != group.connecting_requests.end()) {
|
| RemoveConnectJob(handle);
|
| group.connecting_requests.erase(map_it);
|
| - RemoveActiveSocket(group_name, &group);
|
| + OnAvailableSocketSlot(group_name, &group);
|
| }
|
| }
|
|
|
| @@ -229,9 +242,8 @@ void ClientSocketPoolBase::CleanupIdleSockets(bool force) {
|
| }
|
|
|
| // Delete group if no longer needed.
|
| - if (group.active_socket_count == 0 && group.idle_sockets.empty()) {
|
| + if (group.IsEmpty()) {
|
| CHECK(group.pending_requests.empty());
|
| - CHECK(group.connecting_requests.empty());
|
| group_map_.erase(i++);
|
| } else {
|
| ++i;
|
| @@ -258,9 +270,7 @@ void ClientSocketPoolBase::DoReleaseSocket(const std::string& group_name,
|
| Group& group = i->second;
|
|
|
| CHECK(group.active_socket_count > 0);
|
| - CheckSocketCounts(group);
|
| -
|
| - group.sockets_handed_out_count--;
|
| + group.active_socket_count--;
|
|
|
| const bool can_reuse = socket->IsConnectedAndIdle();
|
| if (can_reuse) {
|
| @@ -274,53 +284,37 @@ void ClientSocketPoolBase::DoReleaseSocket(const std::string& group_name,
|
| delete socket;
|
| }
|
|
|
| - RemoveActiveSocket(group_name, &group);
|
| + OnAvailableSocketSlot(group_name, &group);
|
| }
|
|
|
| -void ClientSocketPoolBase::OnConnectJobComplete(
|
| - const std::string& group_name,
|
| - const ClientSocketHandle* key_handle,
|
| - ClientSocket* socket,
|
| - int result,
|
| - bool was_async) {
|
| +void ClientSocketPoolBase::OnConnectJobComplete(int result, ConnectJob* job) {
|
| + DCHECK_NE(ERR_IO_PENDING, result);
|
| + 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;
|
|
|
| - CheckSocketCounts(group);
|
| -
|
| RequestMap* request_map = &group.connecting_requests;
|
|
|
| - RequestMap::iterator it = request_map->find(key_handle);
|
| + RequestMap::iterator it = request_map->find(job->key_handle());
|
| CHECK(it != request_map->end());
|
| - Request request = it->second;
|
| + ClientSocketHandle* const handle = it->second.handle;
|
| + CompletionCallback* const callback = it->second.callback;
|
| request_map->erase(it);
|
| - DCHECK_EQ(request.handle, key_handle);
|
| + DCHECK_EQ(handle, job->key_handle());
|
|
|
| - if (!socket) {
|
| - RemoveActiveSocket(group_name, &group);
|
| - } else {
|
| - request.handle->set_socket(socket);
|
| - request.handle->set_is_reused(false);
|
| - group.sockets_handed_out_count++;
|
| + ClientSocket* const socket = job->ReleaseSocket();
|
| + RemoveConnectJob(job->key_handle());
|
|
|
| - CheckSocketCounts(group);
|
| + if (result != OK) {
|
| + callback->Run(result); // |group| is not necessarily valid after this.
|
| + // |group| may be invalid after the callback, we need to search
|
| + // |group_map_| again.
|
| + MaybeOnAvailableSocketSlot(group_name);
|
| + } else {
|
| + HandOutSocket(socket, false /* not reused */, handle, &group);
|
| + callback->Run(result);
|
| }
|
| -
|
| - RemoveConnectJob(request.handle);
|
| -
|
| - if (was_async)
|
| - request.callback->Run(result);
|
| -}
|
| -
|
| -// static
|
| -void ClientSocketPoolBase::CheckSocketCounts(const Group& group) {
|
| - CHECK(group.active_socket_count ==
|
| - group.sockets_handed_out_count +
|
| - static_cast<int>(group.connecting_requests.size()))
|
| - << "[active_socket_count: " << group.active_socket_count
|
| - << " ] [sockets_handed_out_count: " << group.sockets_handed_out_count
|
| - << " ] [connecting_requests size: " << group.connecting_requests.size();
|
| }
|
|
|
| void ClientSocketPoolBase::RemoveConnectJob(
|
| @@ -331,20 +325,25 @@ void ClientSocketPoolBase::RemoveConnectJob(
|
| connect_job_map_.erase(it);
|
| }
|
|
|
| -void ClientSocketPoolBase::RemoveActiveSocket(const std::string& group_name,
|
| - Group* group) {
|
| - group->active_socket_count--;
|
| +void ClientSocketPoolBase::MaybeOnAvailableSocketSlot(
|
| + const std::string& group_name) {
|
| + GroupMap::iterator it = group_map_.find(group_name);
|
| + if (it != group_map_.end()) {
|
| + Group& group = it->second;
|
| + if (group.HasAvailableSocketSlot(max_sockets_per_group_))
|
| + OnAvailableSocketSlot(group_name, &group);
|
| + }
|
| +}
|
|
|
| +void ClientSocketPoolBase::OnAvailableSocketSlot(const std::string& group_name,
|
| + Group* group) {
|
| if (!group->pending_requests.empty()) {
|
| ProcessPendingRequest(group_name, group);
|
| // |group| may no longer be valid after this point. Be careful not to
|
| // access it again.
|
| - } else if (group->active_socket_count == 0 && group->idle_sockets.empty()) {
|
| + } else if (group->IsEmpty()) {
|
| // Delete |group| if no longer needed. |group| will no longer be valid.
|
| - DCHECK(group->connecting_requests.empty());
|
| group_map_.erase(group_name);
|
| - } else {
|
| - CheckSocketCounts(*group);
|
| }
|
| }
|
|
|
| @@ -356,10 +355,25 @@ void ClientSocketPoolBase::ProcessPendingRequest(const std::string& group_name,
|
| int rv = RequestSocket(
|
| group_name, r.resolve_info, r.priority, r.handle, r.callback);
|
|
|
| - // |group| may be invalid after RequestSocket.
|
| -
|
| - if (rv != ERR_IO_PENDING)
|
| + if (rv != ERR_IO_PENDING) {
|
| r.callback->Run(rv);
|
| + if (rv != OK) {
|
| + // |group| may be invalid after the callback, we need to search
|
| + // |group_map_| again.
|
| + MaybeOnAvailableSocketSlot(group_name);
|
| + }
|
| + }
|
| +}
|
| +
|
| +void ClientSocketPoolBase::HandOutSocket(
|
| + ClientSocket* socket,
|
| + bool reused,
|
| + ClientSocketHandle* handle,
|
| + Group* group) {
|
| + DCHECK(socket);
|
| + handle->set_socket(socket);
|
| + handle->set_is_reused(reused);
|
| + group->active_socket_count++;
|
| }
|
|
|
| } // namespace net
|
|
|