| 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 |