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 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
218 } | 218 } |
219 | 219 |
220 // Closes all idle sockets if |force| is true. Else, only closes idle | 220 // Closes all idle sockets if |force| is true. Else, only closes idle |
221 // sockets that timed out or can't be reused. Made public for testing. | 221 // sockets that timed out or can't be reused. Made public for testing. |
222 void CleanupIdleSockets(bool force); | 222 void CleanupIdleSockets(bool force); |
223 | 223 |
224 base::TimeDelta ConnectionTimeout() const { | 224 base::TimeDelta ConnectionTimeout() const { |
225 return connect_job_factory_->ConnectionTimeout(); | 225 return connect_job_factory_->ConnectionTimeout(); |
226 } | 226 } |
227 | 227 |
228 void enable_backup_jobs() { backup_jobs_enabled_ = true; }; | 228 void EnableBackupJobs() { backup_jobs_enabled_ = true; }; |
229 | 229 |
230 private: | 230 private: |
231 friend class base::RefCounted<ClientSocketPoolBaseHelper>; | 231 friend class base::RefCounted<ClientSocketPoolBaseHelper>; |
232 | 232 |
233 ~ClientSocketPoolBaseHelper(); | 233 ~ClientSocketPoolBaseHelper(); |
234 | 234 |
235 // Entry for a persistent socket which became idle at time |start_time|. | 235 // Entry for a persistent socket which became idle at time |start_time|. |
236 struct IdleSocket { | 236 struct IdleSocket { |
237 IdleSocket() : socket(NULL), used(false) {} | 237 IdleSocket() : socket(NULL), used(false) {} |
238 ClientSocket* socket; | 238 ClientSocket* socket; |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
380 // |request|. | 380 // |request|. |
381 int RequestSocketInternal(const std::string& group_name, | 381 int RequestSocketInternal(const std::string& group_name, |
382 const Request* request); | 382 const Request* request); |
383 | 383 |
384 // Set a timer to create a backup socket if it takes too long to create one. | 384 // Set a timer to create a backup socket if it takes too long to create one. |
385 void StartBackupSocketTimer(const std::string& group_name); | 385 void StartBackupSocketTimer(const std::string& group_name); |
386 | 386 |
387 // Called when the backup socket timer fires. | 387 // Called when the backup socket timer fires. |
388 void OnBackupSocketTimerFired(const std::string& group_name); | 388 void OnBackupSocketTimerFired(const std::string& group_name); |
389 | 389 |
| 390 // Closes one idle socket. Picks the first one encountered. |
| 391 // TODO(willchan): Consider a better algorithm for doing this. Perhaps we |
| 392 // should keep an ordered list of idle sockets, and close them in order. |
| 393 // Requires maintaining more state. It's not clear if it's worth it since |
| 394 // I'm not sure if we hit this situation often. |
| 395 void CloseOneIdleSocket(); |
| 396 |
390 GroupMap group_map_; | 397 GroupMap group_map_; |
391 | 398 |
392 // Timer used to periodically prune idle sockets that timed out or can't be | 399 // Timer used to periodically prune idle sockets that timed out or can't be |
393 // reused. | 400 // reused. |
394 base::RepeatingTimer<ClientSocketPoolBaseHelper> timer_; | 401 base::RepeatingTimer<ClientSocketPoolBaseHelper> timer_; |
395 | 402 |
396 // The total number of idle sockets in the system. | 403 // The total number of idle sockets in the system. |
397 int idle_socket_count_; | 404 int idle_socket_count_; |
398 | 405 |
399 // Number of connecting sockets across all groups. | 406 // Number of connecting sockets across all groups. |
(...skipping 19 matching lines...) Expand all Loading... |
419 // have pending requests if it exceeds the "max sockets per group" limit. | 426 // have pending requests if it exceeds the "max sockets per group" limit. |
420 // | 427 // |
421 // This means when a socket is released, the only pending requests that can | 428 // This means when a socket is released, the only pending requests that can |
422 // be started next belong to the same group. | 429 // be started next belong to the same group. |
423 // | 430 // |
424 // However once the |max_sockets_| limit is reached, this stops being true: | 431 // However once the |max_sockets_| limit is reached, this stops being true: |
425 // groups can now have pending requests without having first reached the | 432 // groups can now have pending requests without having first reached the |
426 // |max_sockets_per_group_| limit. So choosing the next request involves | 433 // |max_sockets_per_group_| limit. So choosing the next request involves |
427 // selecting the highest priority request across *all* groups. | 434 // selecting the highest priority request across *all* groups. |
428 // | 435 // |
429 // Since reaching the maximum number of sockets is an edge case, we make note | 436 // |may_have_stalled_group_| is not conclusive, since when we cancel pending |
430 // of when it happens, and thus avoid doing the slower "scan all groups" | 437 // requests, we may reach the situation where we have the maximum number of |
431 // in the common case. | 438 // sockets, but not request is stalled because of the global socket limit |
| 439 // (although some requests may be blocked on the socket per group limit). |
| 440 // We don't strictly maintain |may_have_stalled_group_|, since that would |
| 441 // require a linear search through all groups in |group_map_| to see if one |
| 442 // of them is stalled. |
432 bool may_have_stalled_group_; | 443 bool may_have_stalled_group_; |
433 | 444 |
434 const scoped_ptr<ConnectJobFactory> connect_job_factory_; | 445 const scoped_ptr<ConnectJobFactory> connect_job_factory_; |
435 | 446 |
436 // TODO(vandebo) Remove when backup jobs move to TCPClientSocketPool | 447 // TODO(vandebo) Remove when backup jobs move to TCPClientSocketPool |
437 bool backup_jobs_enabled_; | 448 bool backup_jobs_enabled_; |
438 | 449 |
439 // A factory to pin the backup_job tasks. | 450 // A factory to pin the backup_job tasks. |
440 ScopedRunnableMethodFactory<ClientSocketPoolBaseHelper> method_factory_; | 451 ScopedRunnableMethodFactory<ClientSocketPoolBaseHelper> method_factory_; |
441 }; | 452 }; |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
561 void CleanupIdleSockets(bool force) { | 572 void CleanupIdleSockets(bool force) { |
562 return helper_->CleanupIdleSockets(force); | 573 return helper_->CleanupIdleSockets(force); |
563 } | 574 } |
564 | 575 |
565 base::TimeDelta ConnectionTimeout() const { | 576 base::TimeDelta ConnectionTimeout() const { |
566 return helper_->ConnectionTimeout(); | 577 return helper_->ConnectionTimeout(); |
567 } | 578 } |
568 | 579 |
569 const std::string& name() const { return name_; } | 580 const std::string& name() const { return name_; } |
570 | 581 |
571 void enable_backup_jobs() { helper_->enable_backup_jobs(); }; | 582 void EnableBackupJobs() { helper_->EnableBackupJobs(); }; |
572 | 583 |
573 private: | 584 private: |
574 // This adaptor class exists to bridge the | 585 // This adaptor class exists to bridge the |
575 // internal::ClientSocketPoolBaseHelper::ConnectJobFactory and | 586 // internal::ClientSocketPoolBaseHelper::ConnectJobFactory and |
576 // ClientSocketPoolBase::ConnectJobFactory types, allowing clients to use the | 587 // ClientSocketPoolBase::ConnectJobFactory types, allowing clients to use the |
577 // typesafe ClientSocketPoolBase::ConnectJobFactory, rather than having to | 588 // typesafe ClientSocketPoolBase::ConnectJobFactory, rather than having to |
578 // static_cast themselves. | 589 // static_cast themselves. |
579 class ConnectJobFactoryAdaptor | 590 class ConnectJobFactoryAdaptor |
580 : public internal::ClientSocketPoolBaseHelper::ConnectJobFactory { | 591 : public internal::ClientSocketPoolBaseHelper::ConnectJobFactory { |
581 public: | 592 public: |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
613 // the posting of the task and the execution, then we'll hit the DCHECK that | 624 // the posting of the task and the execution, then we'll hit the DCHECK that |
614 // |ClientSocketPoolBaseHelper::group_map_| is empty. | 625 // |ClientSocketPoolBaseHelper::group_map_| is empty. |
615 scoped_refptr<internal::ClientSocketPoolBaseHelper> helper_; | 626 scoped_refptr<internal::ClientSocketPoolBaseHelper> helper_; |
616 | 627 |
617 DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBase); | 628 DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBase); |
618 }; | 629 }; |
619 | 630 |
620 } // namespace net | 631 } // namespace net |
621 | 632 |
622 #endif // NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_ | 633 #endif // NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_ |
OLD | NEW |