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

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

Issue 126065: Make TCPClientSocketPool own the ConnectingSockets. (Closed)
Patch Set: Merge 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/url_request/url_request_unittest.h » ('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 13 matching lines...) Expand all
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
142 if (!synchronous) 122 if (!synchronous)
143 request.callback->Run(result); 123 request.callback->Run(result);
144 delete this; 124 pool_->RemoveConnectingSocket(handle_); // will delete |this|.
145 return result; 125 return result;
146 } 126 }
147 127
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( 128 TCPClientSocketPool::TCPClientSocketPool(
156 int max_sockets_per_group, 129 int max_sockets_per_group,
157 HostResolver* host_resolver, 130 HostResolver* host_resolver,
158 ClientSocketFactory* client_socket_factory) 131 ClientSocketFactory* client_socket_factory)
159 : client_socket_factory_(client_socket_factory), 132 : client_socket_factory_(client_socket_factory),
160 idle_socket_count_(0), 133 idle_socket_count_(0),
161 max_sockets_per_group_(max_sockets_per_group), 134 max_sockets_per_group_(max_sockets_per_group),
162 host_resolver_(host_resolver) { 135 host_resolver_(host_resolver) {
163 } 136 }
164 137
165 TCPClientSocketPool::~TCPClientSocketPool() { 138 TCPClientSocketPool::~TCPClientSocketPool() {
166 // Clean up any idle sockets. Assert that we have no remaining active 139 // 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 140 // sockets or pending requests. They should have all been cleaned up prior
168 // to the manager being destroyed. 141 // to the manager being destroyed.
169 CloseIdleSockets(); 142 CloseIdleSockets();
170 DCHECK(group_map_.empty()); 143 DCHECK(group_map_.empty());
144 DCHECK(connecting_socket_map_.empty());
171 } 145 }
172 146
173 // InsertRequestIntoQueue inserts the request into the queue based on 147 // InsertRequestIntoQueue inserts the request into the queue based on
174 // priority. Highest priorities are closest to the front. Older requests are 148 // priority. Highest priorities are closest to the front. Older requests are
175 // prioritized over requests of equal priority. 149 // prioritized over requests of equal priority.
176 // 150 //
177 // static 151 // static
178 void TCPClientSocketPool::InsertRequestIntoQueue( 152 void TCPClientSocketPool::InsertRequestIntoQueue(
179 const Request& r, RequestQueue* pending_requests) { 153 const Request& r, RequestQueue* pending_requests) {
180 RequestQueue::iterator it = pending_requests->begin(); 154 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! 186 // We found one we can reuse!
213 handle->set_socket(idle_socket.socket); 187 handle->set_socket(idle_socket.socket);
214 handle->set_is_reused(true); 188 handle->set_is_reused(true);
215 return OK; 189 return OK;
216 } 190 }
217 delete idle_socket.socket; 191 delete idle_socket.socket;
218 } 192 }
219 193
220 // We couldn't find a socket to reuse, so allocate and connect a new one. 194 // We couldn't find a socket to reuse, so allocate and connect a new one.
221 195
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); 196 CHECK(callback);
229 Request r(handle, callback, priority, resolve_info, 197 Request r(handle, callback, priority, resolve_info,
230 LOAD_STATE_RESOLVING_HOST); 198 LOAD_STATE_RESOLVING_HOST);
231 group_map_[group_name].connecting_requests[handle] = r; 199 group_map_[group_name].connecting_requests[handle] = r;
232 200
233 // connecting_socket will delete itself. 201 CHECK(!ContainsKey(connecting_socket_map_, handle));
202
234 ConnectingSocket* connecting_socket = 203 ConnectingSocket* connecting_socket =
235 new ConnectingSocket(group_name, handle, client_socket_factory_, this); 204 new ConnectingSocket(group_name, handle, client_socket_factory_, this);
205 connecting_socket_map_[handle] = connecting_socket;
236 int rv = connecting_socket->Connect(resolve_info); 206 int rv = connecting_socket->Connect(resolve_info);
237 return rv; 207 return rv;
238 } 208 }
239 209
240 void TCPClientSocketPool::CancelRequest(const std::string& group_name, 210 void TCPClientSocketPool::CancelRequest(const std::string& group_name,
241 const ClientSocketHandle* handle) { 211 const ClientSocketHandle* handle) {
242 CHECK(ContainsKey(group_map_, group_name)); 212 CHECK(ContainsKey(group_map_, group_name));
243 213
244 Group& group = group_map_[group_name]; 214 Group& group = group_map_[group_name];
245 215
246 // Search pending_requests for matching handle. 216 // Search pending_requests for matching handle.
247 RequestQueue::iterator it = group.pending_requests.begin(); 217 RequestQueue::iterator it = group.pending_requests.begin();
248 for (; it != group.pending_requests.end(); ++it) { 218 for (; it != group.pending_requests.end(); ++it) {
249 if (it->handle == handle) { 219 if (it->handle == handle) {
250 group.pending_requests.erase(it); 220 group.pending_requests.erase(it);
251 return; 221 return;
252 } 222 }
253 } 223 }
254 224
255 // It's invalid to cancel a non-existent request. 225 // It's invalid to cancel a non-existent request.
256 CHECK(ContainsKey(group.connecting_requests, handle)); 226 CHECK(ContainsKey(group.connecting_requests, handle));
257 227
258 RequestMap::iterator map_it = group.connecting_requests.find(handle); 228 RequestMap::iterator map_it = group.connecting_requests.find(handle);
259 if (map_it != group.connecting_requests.end()) { 229 if (map_it != group.connecting_requests.end()) {
230 RemoveConnectingSocket(handle);
231
260 group.connecting_requests.erase(map_it); 232 group.connecting_requests.erase(map_it);
261 group.active_socket_count--; 233 group.active_socket_count--;
262 234
263 // Delete group if no longer needed. 235 // Delete group if no longer needed.
264 if (group.active_socket_count == 0 && group.idle_sockets.empty()) { 236 if (group.active_socket_count == 0 && group.idle_sockets.empty()) {
265 CHECK(group.pending_requests.empty()); 237 CHECK(group.pending_requests.empty());
266 CHECK(group.connecting_requests.empty()); 238 CHECK(group.connecting_requests.empty());
267 group_map_.erase(group_name); 239 group_map_.erase(group_name);
268 } 240 }
269 } 241 }
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
412 } 384 }
413 385
414 // Delete group if no longer needed. 386 // Delete group if no longer needed.
415 if (group.active_socket_count == 0 && group.idle_sockets.empty()) { 387 if (group.active_socket_count == 0 && group.idle_sockets.empty()) {
416 CHECK(group.pending_requests.empty()); 388 CHECK(group.pending_requests.empty());
417 CHECK(group.connecting_requests.empty()); 389 CHECK(group.connecting_requests.empty());
418 group_map_.erase(i); 390 group_map_.erase(i);
419 } 391 }
420 } 392 }
421 393
394 void TCPClientSocketPool::RemoveConnectingSocket(
395 const ClientSocketHandle* handle) {
396 ConnectingSocketMap::iterator it = connecting_socket_map_.find(handle);
397 CHECK(it != connecting_socket_map_.end());
398 delete it->second;
399 connecting_socket_map_.erase(it);
400 }
401
422 } // namespace net 402 } // namespace net
OLDNEW
« no previous file with comments | « net/base/tcp_client_socket_pool.h ('k') | net/url_request/url_request_unittest.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698