Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(161)

Side by Side Diff: net/base/tcp_client_socket_pool.cc

Issue 126168: Take 2. Make TCPClientSocketPool own the ConnectingSockets. (Closed)
Patch Set: Created 11 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/base/tcp_client_socket_pool.h ('k') | net/base/tcp_client_socket_pool_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/base/tcp_client_socket_pool.h" 5 #include "net/base/tcp_client_socket_pool.h"
6 6
7 #include "base/compiler_specific.h" 7 #include "base/compiler_specific.h"
8 #include "base/field_trial.h" 8 #include "base/field_trial.h"
9 #include "base/message_loop.h" 9 #include "base/message_loop.h"
10 #include "base/time.h" 10 #include "base/time.h"
(...skipping 27 matching lines...) Expand all
38 const ClientSocketHandle* handle, 38 const ClientSocketHandle* handle,
39 ClientSocketFactory* client_socket_factory, 39 ClientSocketFactory* client_socket_factory,
40 TCPClientSocketPool* pool) 40 TCPClientSocketPool* pool)
41 : group_name_(group_name), 41 : group_name_(group_name),
42 handle_(handle), 42 handle_(handle),
43 client_socket_factory_(client_socket_factory), 43 client_socket_factory_(client_socket_factory),
44 ALLOW_THIS_IN_INITIALIZER_LIST( 44 ALLOW_THIS_IN_INITIALIZER_LIST(
45 callback_(this, 45 callback_(this,
46 &TCPClientSocketPool::ConnectingSocket::OnIOComplete)), 46 &TCPClientSocketPool::ConnectingSocket::OnIOComplete)),
47 pool_(pool), 47 pool_(pool),
48 resolver_(pool->GetHostResolver()), 48 resolver_(pool->GetHostResolver()) {}
49 canceled_(false) {
50 CHECK(!ContainsKey(pool_->connecting_socket_map_, handle));
51 pool_->connecting_socket_map_[handle] = this;
52 }
53 49
54 TCPClientSocketPool::ConnectingSocket::~ConnectingSocket() { 50 TCPClientSocketPool::ConnectingSocket::~ConnectingSocket() {
55 if (!canceled_) 51 // We don't worry about cancelling the host resolution and TCP connect, since
56 pool_->connecting_socket_map_.erase(handle_); 52 // ~SingleRequestHostResolver and ~ClientSocket will take care of it.
57 } 53 }
58 54
59 int TCPClientSocketPool::ConnectingSocket::Connect( 55 int TCPClientSocketPool::ConnectingSocket::Connect(
60 const HostResolver::RequestInfo& resolve_info) { 56 const HostResolver::RequestInfo& resolve_info) {
61 CHECK(!canceled_);
62 int rv = resolver_.Resolve(resolve_info, &addresses_, &callback_); 57 int rv = resolver_.Resolve(resolve_info, &addresses_, &callback_);
63 if (rv != ERR_IO_PENDING) 58 if (rv != ERR_IO_PENDING)
64 rv = OnIOCompleteInternal(rv, true /* synchronous */); 59 rv = OnIOCompleteInternal(rv, true /* synchronous */);
65 return rv; 60 return rv;
66 } 61 }
67 62
68 void TCPClientSocketPool::ConnectingSocket::OnIOComplete(int result) { 63 void TCPClientSocketPool::ConnectingSocket::OnIOComplete(int result) {
69 OnIOCompleteInternal(result, false /* asynchronous */); 64 OnIOCompleteInternal(result, false /* asynchronous */);
70 } 65 }
71 66
72 int TCPClientSocketPool::ConnectingSocket::OnIOCompleteInternal( 67 int TCPClientSocketPool::ConnectingSocket::OnIOCompleteInternal(
73 int result, bool synchronous) { 68 int result, bool synchronous) {
74 CHECK(result != ERR_IO_PENDING); 69 CHECK(result != ERR_IO_PENDING);
75 70
76 if (canceled_) {
77 // We got canceled, so bail out.
78 delete this;
79 return result;
80 }
81
82 GroupMap::iterator group_it = pool_->group_map_.find(group_name_); 71 GroupMap::iterator group_it = pool_->group_map_.find(group_name_);
83 if (group_it == pool_->group_map_.end()) { 72 CHECK(group_it != pool_->group_map_.end());
84 // The request corresponding to this ConnectingSocket has been canceled.
85 // Stop bothering with it.
86 delete this;
87 return result;
88 }
89 73
90 Group& group = group_it->second; 74 Group& group = group_it->second;
91 75
92 RequestMap* request_map = &group.connecting_requests; 76 RequestMap* request_map = &group.connecting_requests;
93 RequestMap::iterator it = request_map->find(handle_); 77 RequestMap::iterator it = request_map->find(handle_);
94 if (it == request_map->end()) { 78 CHECK(it != request_map->end());
95 // The request corresponding to this ConnectingSocket has been canceled.
96 // Stop bothering with it.
97 delete this;
98 return result;
99 }
100 79
101 if (result == OK && it->second.load_state == LOAD_STATE_RESOLVING_HOST) { 80 if (result == OK && it->second.load_state == LOAD_STATE_RESOLVING_HOST) {
102 it->second.load_state = LOAD_STATE_CONNECTING; 81 it->second.load_state = LOAD_STATE_CONNECTING;
103 socket_.reset(client_socket_factory_->CreateTCPClientSocket(addresses_)); 82 socket_.reset(client_socket_factory_->CreateTCPClientSocket(addresses_));
104 connect_start_time_ = base::Time::Now(); 83 connect_start_time_ = base::Time::Now();
105 result = socket_->Connect(&callback_); 84 result = socket_->Connect(&callback_);
106 if (result == ERR_IO_PENDING) 85 if (result == ERR_IO_PENDING)
107 return result; 86 return result;
108 } 87 }
109 88
110 if (result == OK) { 89 if (result == OK) {
90 CHECK(it->second.load_state == LOAD_STATE_CONNECTING);
111 CHECK(connect_start_time_ != base::Time()); 91 CHECK(connect_start_time_ != base::Time());
112 base::TimeDelta connect_duration = 92 base::TimeDelta connect_duration =
113 base::Time::Now() - connect_start_time_; 93 base::Time::Now() - connect_start_time_;
114 94
115 UMA_HISTOGRAM_CLIPPED_TIMES("Net.TCP_Connection_Latency", 95 UMA_HISTOGRAM_CLIPPED_TIMES("Net.TCP_Connection_Latency",
116 connect_duration, 96 connect_duration,
117 base::TimeDelta::FromMilliseconds(1), 97 base::TimeDelta::FromMilliseconds(1),
118 base::TimeDelta::FromMinutes(10), 98 base::TimeDelta::FromMinutes(10),
119 100); 99 100);
120 } 100 }
(...skipping 11 matching lines...) Expand all
132 group.active_socket_count--; 112 group.active_socket_count--;
133 113
134 // Delete group if no longer needed. 114 // Delete group if no longer needed.
135 if (group.active_socket_count == 0 && group.idle_sockets.empty()) { 115 if (group.active_socket_count == 0 && group.idle_sockets.empty()) {
136 CHECK(group.pending_requests.empty()); 116 CHECK(group.pending_requests.empty());
137 CHECK(group.connecting_requests.empty()); 117 CHECK(group.connecting_requests.empty());
138 pool_->group_map_.erase(group_it); 118 pool_->group_map_.erase(group_it);
139 } 119 }
140 } 120 }
141 121
122 pool_->RemoveConnectingSocket(handle_); // will delete |this|.
123
142 if (!synchronous) 124 if (!synchronous)
143 request.callback->Run(result); 125 request.callback->Run(result);
144 delete this;
145 return result; 126 return result;
146 } 127 }
147 128
148 void TCPClientSocketPool::ConnectingSocket::Cancel() {
149 CHECK(!canceled_);
150 CHECK(ContainsKey(pool_->connecting_socket_map_, handle_));
151 pool_->connecting_socket_map_.erase(handle_);
152 canceled_ = true;
153 }
154
155 TCPClientSocketPool::TCPClientSocketPool( 129 TCPClientSocketPool::TCPClientSocketPool(
156 int max_sockets_per_group, 130 int max_sockets_per_group,
157 HostResolver* host_resolver, 131 HostResolver* host_resolver,
158 ClientSocketFactory* client_socket_factory) 132 ClientSocketFactory* client_socket_factory)
159 : client_socket_factory_(client_socket_factory), 133 : client_socket_factory_(client_socket_factory),
160 idle_socket_count_(0), 134 idle_socket_count_(0),
161 max_sockets_per_group_(max_sockets_per_group), 135 max_sockets_per_group_(max_sockets_per_group),
162 host_resolver_(host_resolver) { 136 host_resolver_(host_resolver) {
163 } 137 }
164 138
165 TCPClientSocketPool::~TCPClientSocketPool() { 139 TCPClientSocketPool::~TCPClientSocketPool() {
166 // Clean up any idle sockets. Assert that we have no remaining active 140 // Clean up any idle sockets. Assert that we have no remaining active
167 // sockets or pending requests. They should have all been cleaned up prior 141 // sockets or pending requests. They should have all been cleaned up prior
168 // to the manager being destroyed. 142 // to the manager being destroyed.
169 CloseIdleSockets(); 143 CloseIdleSockets();
170 DCHECK(group_map_.empty()); 144 DCHECK(group_map_.empty());
145 DCHECK(connecting_socket_map_.empty());
171 } 146 }
172 147
173 // InsertRequestIntoQueue inserts the request into the queue based on 148 // InsertRequestIntoQueue inserts the request into the queue based on
174 // priority. Highest priorities are closest to the front. Older requests are 149 // priority. Highest priorities are closest to the front. Older requests are
175 // prioritized over requests of equal priority. 150 // prioritized over requests of equal priority.
176 // 151 //
177 // static 152 // static
178 void TCPClientSocketPool::InsertRequestIntoQueue( 153 void TCPClientSocketPool::InsertRequestIntoQueue(
179 const Request& r, RequestQueue* pending_requests) { 154 const Request& r, RequestQueue* pending_requests) {
180 RequestQueue::iterator it = pending_requests->begin(); 155 RequestQueue::iterator it = pending_requests->begin();
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
212 // We found one we can reuse! 187 // We found one we can reuse!
213 handle->set_socket(idle_socket.socket); 188 handle->set_socket(idle_socket.socket);
214 handle->set_is_reused(true); 189 handle->set_is_reused(true);
215 return OK; 190 return OK;
216 } 191 }
217 delete idle_socket.socket; 192 delete idle_socket.socket;
218 } 193 }
219 194
220 // We couldn't find a socket to reuse, so allocate and connect a new one. 195 // We couldn't find a socket to reuse, so allocate and connect a new one.
221 196
222 // First, we need to make sure we aren't already servicing a request for this
223 // handle (which could happen if we requested, canceled, and then requested
224 // with the same handle).
225 if (ContainsKey(connecting_socket_map_, handle))
226 connecting_socket_map_[handle]->Cancel();
227
228 CHECK(callback); 197 CHECK(callback);
229 Request r(handle, callback, priority, resolve_info, 198 Request r(handle, callback, priority, resolve_info,
230 LOAD_STATE_RESOLVING_HOST); 199 LOAD_STATE_RESOLVING_HOST);
231 group_map_[group_name].connecting_requests[handle] = r; 200 group_map_[group_name].connecting_requests[handle] = r;
232 201
233 // connecting_socket will delete itself. 202 CHECK(!ContainsKey(connecting_socket_map_, handle));
203
234 ConnectingSocket* connecting_socket = 204 ConnectingSocket* connecting_socket =
235 new ConnectingSocket(group_name, handle, client_socket_factory_, this); 205 new ConnectingSocket(group_name, handle, client_socket_factory_, this);
206 connecting_socket_map_[handle] = connecting_socket;
236 int rv = connecting_socket->Connect(resolve_info); 207 int rv = connecting_socket->Connect(resolve_info);
237 return rv; 208 return rv;
238 } 209 }
239 210
240 void TCPClientSocketPool::CancelRequest(const std::string& group_name, 211 void TCPClientSocketPool::CancelRequest(const std::string& group_name,
241 const ClientSocketHandle* handle) { 212 const ClientSocketHandle* handle) {
242 CHECK(ContainsKey(group_map_, group_name)); 213 CHECK(ContainsKey(group_map_, group_name));
243 214
244 Group& group = group_map_[group_name]; 215 Group& group = group_map_[group_name];
245 216
246 // Search pending_requests for matching handle. 217 // Search pending_requests for matching handle.
247 RequestQueue::iterator it = group.pending_requests.begin(); 218 RequestQueue::iterator it = group.pending_requests.begin();
248 for (; it != group.pending_requests.end(); ++it) { 219 for (; it != group.pending_requests.end(); ++it) {
249 if (it->handle == handle) { 220 if (it->handle == handle) {
250 group.pending_requests.erase(it); 221 group.pending_requests.erase(it);
251 return; 222 return;
252 } 223 }
253 } 224 }
254 225
255 // It's invalid to cancel a non-existent request. 226 // It's invalid to cancel a non-existent request.
256 CHECK(ContainsKey(group.connecting_requests, handle)); 227 CHECK(ContainsKey(group.connecting_requests, handle));
257 228
258 RequestMap::iterator map_it = group.connecting_requests.find(handle); 229 RequestMap::iterator map_it = group.connecting_requests.find(handle);
259 if (map_it != group.connecting_requests.end()) { 230 if (map_it != group.connecting_requests.end()) {
231 RemoveConnectingSocket(handle);
232
260 group.connecting_requests.erase(map_it); 233 group.connecting_requests.erase(map_it);
261 group.active_socket_count--; 234 group.active_socket_count--;
262 235
263 // Delete group if no longer needed. 236 // Delete group if no longer needed.
264 if (group.active_socket_count == 0 && group.idle_sockets.empty()) { 237 if (group.active_socket_count == 0 && group.idle_sockets.empty()) {
265 CHECK(group.pending_requests.empty()); 238 CHECK(group.pending_requests.empty());
266 CHECK(group.connecting_requests.empty()); 239 CHECK(group.connecting_requests.empty());
267 group_map_.erase(group_name); 240 group_map_.erase(group_name);
268 } 241 }
269 } 242 }
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
412 } 385 }
413 386
414 // Delete group if no longer needed. 387 // Delete group if no longer needed.
415 if (group.active_socket_count == 0 && group.idle_sockets.empty()) { 388 if (group.active_socket_count == 0 && group.idle_sockets.empty()) {
416 CHECK(group.pending_requests.empty()); 389 CHECK(group.pending_requests.empty());
417 CHECK(group.connecting_requests.empty()); 390 CHECK(group.connecting_requests.empty());
418 group_map_.erase(i); 391 group_map_.erase(i);
419 } 392 }
420 } 393 }
421 394
395 void TCPClientSocketPool::RemoveConnectingSocket(
396 const ClientSocketHandle* handle) {
397 ConnectingSocketMap::iterator it = connecting_socket_map_.find(handle);
398 CHECK(it != connecting_socket_map_.end());
399 delete it->second;
400 connecting_socket_map_.erase(it);
401 }
402
422 } // namespace net 403 } // namespace net
OLDNEW
« no previous file with comments | « net/base/tcp_client_socket_pool.h ('k') | net/base/tcp_client_socket_pool_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698