OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 // A ClientSocketPoolBase is used to restrict the number of sockets open at | 5 // A ClientSocketPoolBase is used to restrict the number of sockets open at |
6 // a time. It also maintains a list of idle persistent sockets for reuse. | 6 // a time. It also maintains a list of idle persistent sockets for reuse. |
7 // Subclasses of ClientSocketPool should compose ClientSocketPoolBase to handle | 7 // Subclasses of ClientSocketPool should compose ClientSocketPoolBase to handle |
8 // the core logic of (1) restricting the number of active (connected or | 8 // the core logic of (1) restricting the number of active (connected or |
9 // connecting) sockets per "group" (generally speaking, the hostname), (2) | 9 // connecting) sockets per "group" (generally speaking, the hostname), (2) |
10 // maintaining a per-group list of idle, persistent sockets for reuse, and (3) | 10 // maintaining a per-group list of idle, persistent sockets for reuse, and (3) |
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
232 } | 232 } |
233 | 233 |
234 // Closes all idle sockets if |force| is true. Else, only closes idle | 234 // Closes all idle sockets if |force| is true. Else, only closes idle |
235 // sockets that timed out or can't be reused. Made public for testing. | 235 // sockets that timed out or can't be reused. Made public for testing. |
236 void CleanupIdleSockets(bool force); | 236 void CleanupIdleSockets(bool force); |
237 | 237 |
238 base::TimeDelta ConnectionTimeout() const { | 238 base::TimeDelta ConnectionTimeout() const { |
239 return connect_job_factory_->ConnectionTimeout(); | 239 return connect_job_factory_->ConnectionTimeout(); |
240 } | 240 } |
241 | 241 |
242 void EnableBackupJobs() { backup_jobs_enabled_ = true; } | 242 static void set_connect_backup_jobs_enabled(bool enabled); |
| 243 void EnableConnectBackupJobs(); |
243 | 244 |
244 private: | 245 private: |
245 friend class base::RefCounted<ClientSocketPoolBaseHelper>; | 246 friend class base::RefCounted<ClientSocketPoolBaseHelper>; |
246 | 247 |
247 // Entry for a persistent socket which became idle at time |start_time|. | 248 // Entry for a persistent socket which became idle at time |start_time|. |
248 struct IdleSocket { | 249 struct IdleSocket { |
249 IdleSocket() : socket(NULL), used(false) {} | 250 IdleSocket() : socket(NULL), used(false) {} |
250 ClientSocket* socket; | 251 ClientSocket* socket; |
251 base::TimeTicks start_time; | 252 base::TimeTicks start_time; |
252 bool used; // Indicates whether or not the socket has been used yet. | 253 bool used; // Indicates whether or not the socket has been used yet. |
(...skipping 11 matching lines...) Expand all Loading... |
264 | 265 |
265 typedef std::deque<const Request*> RequestQueue; | 266 typedef std::deque<const Request*> RequestQueue; |
266 typedef std::map<const ClientSocketHandle*, const Request*> RequestMap; | 267 typedef std::map<const ClientSocketHandle*, const Request*> RequestMap; |
267 | 268 |
268 // A Group is allocated per group_name when there are idle sockets or pending | 269 // A Group is allocated per group_name when there are idle sockets or pending |
269 // requests. Otherwise, the Group object is removed from the map. | 270 // requests. Otherwise, the Group object is removed from the map. |
270 // |active_socket_count| tracks the number of sockets held by clients. | 271 // |active_socket_count| tracks the number of sockets held by clients. |
271 struct Group { | 272 struct Group { |
272 Group() | 273 Group() |
273 : active_socket_count(0), | 274 : active_socket_count(0), |
274 backup_job(NULL), | 275 connect_backup_job(NULL), |
275 backup_task(NULL) { | 276 backup_task(NULL) { |
276 } | 277 } |
277 | 278 |
278 ~Group() { | 279 ~Group() { |
279 CleanupBackupJob(); | 280 CleanupBackupJob(); |
280 } | 281 } |
281 | 282 |
282 bool IsEmpty() const { | 283 bool IsEmpty() const { |
283 return active_socket_count == 0 && idle_sockets.empty() && jobs.empty() && | 284 return active_socket_count == 0 && idle_sockets.empty() && jobs.empty() && |
284 pending_requests.empty(); | 285 pending_requests.empty(); |
285 } | 286 } |
286 | 287 |
287 bool HasAvailableSocketSlot(int max_sockets_per_group) const { | 288 bool HasAvailableSocketSlot(int max_sockets_per_group) const { |
288 return active_socket_count + static_cast<int>(jobs.size()) < | 289 return active_socket_count + static_cast<int>(jobs.size()) < |
289 max_sockets_per_group; | 290 max_sockets_per_group; |
290 } | 291 } |
291 | 292 |
292 bool IsStalled(int max_sockets_per_group) const { | 293 bool IsStalled(int max_sockets_per_group) const { |
293 return HasAvailableSocketSlot(max_sockets_per_group) && | 294 return HasAvailableSocketSlot(max_sockets_per_group) && |
294 pending_requests.size() > jobs.size(); | 295 pending_requests.size() > jobs.size(); |
295 } | 296 } |
296 | 297 |
297 RequestPriority TopPendingPriority() const { | 298 RequestPriority TopPendingPriority() const { |
298 return pending_requests.front()->priority(); | 299 return pending_requests.front()->priority(); |
299 } | 300 } |
300 | 301 |
301 void CleanupBackupJob() { | 302 void CleanupBackupJob() { |
302 if (backup_job) { | 303 if (connect_backup_job) { |
303 delete backup_job; | 304 delete connect_backup_job; |
304 backup_job = NULL; | 305 connect_backup_job = NULL; |
305 } | 306 } |
306 if (backup_task) { | 307 if (backup_task) { |
307 backup_task->Cancel(); | 308 backup_task->Cancel(); |
308 backup_task = NULL; | 309 backup_task = NULL; |
309 } | 310 } |
310 } | 311 } |
311 | 312 |
312 std::deque<IdleSocket> idle_sockets; | 313 std::deque<IdleSocket> idle_sockets; |
313 std::set<const ConnectJob*> jobs; | 314 std::set<const ConnectJob*> jobs; |
314 RequestQueue pending_requests; | 315 RequestQueue pending_requests; |
315 int active_socket_count; // number of active sockets used by clients | 316 int active_socket_count; // number of active sockets used by clients |
316 // A backup job in case the connect for this group takes too long. | 317 // A backup job in case the connect for this group takes too long. |
317 ConnectJob* backup_job; | 318 ConnectJob* connect_backup_job; |
318 CancelableTask* backup_task; | 319 CancelableTask* backup_task; |
319 }; | 320 }; |
320 | 321 |
321 typedef std::map<std::string, Group> GroupMap; | 322 typedef std::map<std::string, Group> GroupMap; |
322 | 323 |
323 typedef std::set<const ConnectJob*> ConnectJobSet; | 324 typedef std::set<const ConnectJob*> ConnectJobSet; |
324 | 325 |
325 struct CallbackResultPair { | 326 struct CallbackResultPair { |
326 CallbackResultPair() : callback(NULL), result(OK) {} | 327 CallbackResultPair() : callback(NULL), result(OK) {} |
327 CallbackResultPair(CompletionCallback* callback_in, int result_in) | 328 CallbackResultPair(CompletionCallback* callback_in, int result_in) |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
454 // The maximum number of sockets kept per group. | 455 // The maximum number of sockets kept per group. |
455 const int max_sockets_per_group_; | 456 const int max_sockets_per_group_; |
456 | 457 |
457 // The time to wait until closing idle sockets. | 458 // The time to wait until closing idle sockets. |
458 const base::TimeDelta unused_idle_socket_timeout_; | 459 const base::TimeDelta unused_idle_socket_timeout_; |
459 const base::TimeDelta used_idle_socket_timeout_; | 460 const base::TimeDelta used_idle_socket_timeout_; |
460 | 461 |
461 const scoped_ptr<ConnectJobFactory> connect_job_factory_; | 462 const scoped_ptr<ConnectJobFactory> connect_job_factory_; |
462 | 463 |
463 // TODO(vandebo) Remove when backup jobs move to TCPClientSocketPool | 464 // TODO(vandebo) Remove when backup jobs move to TCPClientSocketPool |
464 bool backup_jobs_enabled_; | 465 bool connect_backup_jobs_enabled_; |
465 | 466 |
466 // A factory to pin the backup_job tasks. | 467 // A factory to pin the backup_job tasks. |
467 ScopedRunnableMethodFactory<ClientSocketPoolBaseHelper> method_factory_; | 468 ScopedRunnableMethodFactory<ClientSocketPoolBaseHelper> method_factory_; |
468 | 469 |
469 // A unique id for the pool. It gets incremented every time we Flush() the | 470 // A unique id for the pool. It gets incremented every time we Flush() the |
470 // pool. This is so that when sockets get released back to the pool, we can | 471 // pool. This is so that when sockets get released back to the pool, we can |
471 // make sure that they are discarded rather than reused. | 472 // make sure that they are discarded rather than reused. |
472 int pool_generation_number_; | 473 int pool_generation_number_; |
473 | 474 |
474 // Some parts of this class need to know if the destructor is running. | 475 // Some parts of this class need to know if the destructor is running. |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
588 } | 589 } |
589 | 590 |
590 base::TimeDelta ConnectionTimeout() const { | 591 base::TimeDelta ConnectionTimeout() const { |
591 return helper_->ConnectionTimeout(); | 592 return helper_->ConnectionTimeout(); |
592 } | 593 } |
593 | 594 |
594 scoped_refptr<ClientSocketPoolHistograms> histograms() const { | 595 scoped_refptr<ClientSocketPoolHistograms> histograms() const { |
595 return histograms_; | 596 return histograms_; |
596 } | 597 } |
597 | 598 |
598 void EnableBackupJobs() { helper_->EnableBackupJobs(); } | 599 void EnableConnectBackupJobs() { helper_->EnableConnectBackupJobs(); } |
599 | 600 |
600 void Flush() { helper_->Flush(); } | 601 void Flush() { helper_->Flush(); } |
601 | 602 |
602 private: | 603 private: |
603 // This adaptor class exists to bridge the | 604 // This adaptor class exists to bridge the |
604 // internal::ClientSocketPoolBaseHelper::ConnectJobFactory and | 605 // internal::ClientSocketPoolBaseHelper::ConnectJobFactory and |
605 // ClientSocketPoolBase::ConnectJobFactory types, allowing clients to use the | 606 // ClientSocketPoolBase::ConnectJobFactory types, allowing clients to use the |
606 // typesafe ClientSocketPoolBase::ConnectJobFactory, rather than having to | 607 // typesafe ClientSocketPoolBase::ConnectJobFactory, rather than having to |
607 // static_cast themselves. | 608 // static_cast themselves. |
608 class ConnectJobFactoryAdaptor | 609 class ConnectJobFactoryAdaptor |
(...skipping 30 matching lines...) Expand all Loading... |
639 // ClientSocketPoolBase<T> reference to drop to zero. While we're deep | 640 // ClientSocketPoolBase<T> reference to drop to zero. While we're deep |
640 // in cleanup code, we'll often hold a reference to |self|. | 641 // in cleanup code, we'll often hold a reference to |self|. |
641 scoped_refptr<internal::ClientSocketPoolBaseHelper> helper_; | 642 scoped_refptr<internal::ClientSocketPoolBaseHelper> helper_; |
642 | 643 |
643 DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBase); | 644 DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBase); |
644 }; | 645 }; |
645 | 646 |
646 } // namespace net | 647 } // namespace net |
647 | 648 |
648 #endif // NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_ | 649 #endif // NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_ |
OLD | NEW |