| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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) |
| 11 // limiting the total number of active sockets in the system. | 11 // limiting the total number of active sockets in the system. |
| 12 // | 12 // |
| 13 // ClientSocketPoolBase abstracts socket connection details behind ConnectJob, | 13 // ClientSocketPoolBase abstracts socket connection details behind ConnectJob, |
| 14 // ConnectJobFactory, and SocketParams. When a socket "slot" becomes available, | 14 // ConnectJobFactory, and SocketParams. When a socket "slot" becomes available, |
| 15 // the ClientSocketPoolBase will ask the ConnectJobFactory to create a | 15 // the ClientSocketPoolBase will ask the ConnectJobFactory to create a |
| 16 // ConnectJob with a SocketParams. Subclasses of ClientSocketPool should | 16 // ConnectJob with a SocketParams. Subclasses of ClientSocketPool should |
| 17 // implement their socket specific connection by subclassing ConnectJob and | 17 // implement their socket specific connection by subclassing ConnectJob and |
| 18 // implementing ConnectJob::ConnectInternal(). They can control the parameters | 18 // implementing ConnectJob::ConnectInternal(). They can control the parameters |
| 19 // passed to each new ConnectJob instance via their ConnectJobFactory subclass | 19 // passed to each new ConnectJob instance via their ConnectJobFactory subclass |
| 20 // and templated SocketParams parameter. | 20 // and templated SocketParams parameter. |
| 21 // | 21 // |
| 22 #ifndef NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_ | 22 #ifndef NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_ |
| 23 #define NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_ | 23 #define NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_ |
| 24 #pragma once | 24 #pragma once |
| 25 | 25 |
| 26 #include <deque> | 26 #include <deque> |
| 27 #include <list> | 27 #include <list> |
| 28 #include <map> | 28 #include <map> |
| 29 #include <set> | 29 #include <set> |
| 30 #include <string> | 30 #include <string> |
| 31 #include <vector> | |
| 32 | 31 |
| 33 #include "base/basictypes.h" | 32 #include "base/basictypes.h" |
| 34 #include "base/memory/ref_counted.h" | 33 #include "base/memory/ref_counted.h" |
| 35 #include "base/memory/scoped_ptr.h" | 34 #include "base/memory/scoped_ptr.h" |
| 36 #include "base/memory/weak_ptr.h" | 35 #include "base/memory/weak_ptr.h" |
| 37 #include "base/time.h" | 36 #include "base/time.h" |
| 38 #include "base/timer.h" | 37 #include "base/timer.h" |
| 39 #include "net/base/address_list.h" | 38 #include "net/base/address_list.h" |
| 40 #include "net/base/completion_callback.h" | 39 #include "net/base/completion_callback.h" |
| 41 #include "net/base/load_states.h" | 40 #include "net/base/load_states.h" |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 233 | 232 |
| 234 ClientSocketPoolBaseHelper( | 233 ClientSocketPoolBaseHelper( |
| 235 int max_sockets, | 234 int max_sockets, |
| 236 int max_sockets_per_group, | 235 int max_sockets_per_group, |
| 237 base::TimeDelta unused_idle_socket_timeout, | 236 base::TimeDelta unused_idle_socket_timeout, |
| 238 base::TimeDelta used_idle_socket_timeout, | 237 base::TimeDelta used_idle_socket_timeout, |
| 239 ConnectJobFactory* connect_job_factory); | 238 ConnectJobFactory* connect_job_factory); |
| 240 | 239 |
| 241 virtual ~ClientSocketPoolBaseHelper(); | 240 virtual ~ClientSocketPoolBaseHelper(); |
| 242 | 241 |
| 243 // Adds/Removes layered pools. It is expected in the destructor that no | |
| 244 // layered pools remain. | |
| 245 void AddLayeredPool(LayeredPool* pool); | |
| 246 void RemoveLayeredPool(LayeredPool* pool); | |
| 247 | |
| 248 // See ClientSocketPool::RequestSocket for documentation on this function. | 242 // See ClientSocketPool::RequestSocket for documentation on this function. |
| 249 // ClientSocketPoolBaseHelper takes ownership of |request|, which must be | 243 // ClientSocketPoolBaseHelper takes ownership of |request|, which must be |
| 250 // heap allocated. | 244 // heap allocated. |
| 251 int RequestSocket(const std::string& group_name, const Request* request); | 245 int RequestSocket(const std::string& group_name, const Request* request); |
| 252 | 246 |
| 253 // See ClientSocketPool::RequestSocket for documentation on this function. | 247 // See ClientSocketPool::RequestSocket for documentation on this function. |
| 254 void RequestSockets(const std::string& group_name, | 248 void RequestSockets(const std::string& group_name, |
| 255 const Request& request, | 249 const Request& request, |
| 256 int num_sockets); | 250 int num_sockets); |
| 257 | 251 |
| 258 // See ClientSocketPool::CancelRequest for documentation on this function. | 252 // See ClientSocketPool::CancelRequest for documentation on this function. |
| 259 void CancelRequest(const std::string& group_name, | 253 void CancelRequest(const std::string& group_name, |
| 260 ClientSocketHandle* handle); | 254 ClientSocketHandle* handle); |
| 261 | 255 |
| 262 // See ClientSocketPool::ReleaseSocket for documentation on this function. | 256 // See ClientSocketPool::ReleaseSocket for documentation on this function. |
| 263 void ReleaseSocket(const std::string& group_name, | 257 void ReleaseSocket(const std::string& group_name, |
| 264 StreamSocket* socket, | 258 StreamSocket* socket, |
| 265 int id); | 259 int id); |
| 266 | 260 |
| 267 // See ClientSocketPool::Flush for documentation on this function. | 261 // See ClientSocketPool::Flush for documentation on this function. |
| 268 void Flush(); | 262 void Flush(); |
| 269 | 263 |
| 270 // See ClientSocketPool::IsStalled for documentation on this function. | |
| 271 bool IsStalled() const; | |
| 272 | |
| 273 // See ClientSocketPool::CloseIdleSockets for documentation on this function. | 264 // See ClientSocketPool::CloseIdleSockets for documentation on this function. |
| 274 void CloseIdleSockets(); | 265 void CloseIdleSockets(); |
| 275 | 266 |
| 276 // See ClientSocketPool::IdleSocketCount() for documentation on this function. | 267 // See ClientSocketPool::IdleSocketCount() for documentation on this function. |
| 277 int idle_socket_count() const { | 268 int idle_socket_count() const { |
| 278 return idle_socket_count_; | 269 return idle_socket_count_; |
| 279 } | 270 } |
| 280 | 271 |
| 281 // See ClientSocketPool::IdleSocketCountInGroup() for documentation on this | 272 // See ClientSocketPool::IdleSocketCountInGroup() for documentation on this |
| 282 // function. | 273 // function. |
| (...skipping 24 matching lines...) Expand all Loading... |
| 307 // by kCleanupInterval are cleaned up using a timer. Otherwise they are | 298 // by kCleanupInterval are cleaned up using a timer. Otherwise they are |
| 308 // closed next time client makes a request. This may reduce network | 299 // closed next time client makes a request. This may reduce network |
| 309 // activity and power consumption. | 300 // activity and power consumption. |
| 310 static bool cleanup_timer_enabled(); | 301 static bool cleanup_timer_enabled(); |
| 311 static bool set_cleanup_timer_enabled(bool enabled); | 302 static bool set_cleanup_timer_enabled(bool enabled); |
| 312 | 303 |
| 313 // Closes all idle sockets if |force| is true. Else, only closes idle | 304 // Closes all idle sockets if |force| is true. Else, only closes idle |
| 314 // sockets that timed out or can't be reused. Made public for testing. | 305 // sockets that timed out or can't be reused. Made public for testing. |
| 315 void CleanupIdleSockets(bool force); | 306 void CleanupIdleSockets(bool force); |
| 316 | 307 |
| 317 // Closes one idle socket. Picks the first one encountered. | |
| 318 // TODO(willchan): Consider a better algorithm for doing this. Perhaps we | |
| 319 // should keep an ordered list of idle sockets, and close them in order. | |
| 320 // Requires maintaining more state. It's not clear if it's worth it since | |
| 321 // I'm not sure if we hit this situation often. | |
| 322 bool CloseOneIdleSocket(); | |
| 323 | |
| 324 // Checks layered pools to see if they can close an idle connection. | |
| 325 bool CloseOneIdleConnectionInLayeredPool(); | |
| 326 | |
| 327 // See ClientSocketPool::GetInfoAsValue for documentation on this function. | 308 // See ClientSocketPool::GetInfoAsValue for documentation on this function. |
| 328 base::DictionaryValue* GetInfoAsValue(const std::string& name, | 309 base::DictionaryValue* GetInfoAsValue(const std::string& name, |
| 329 const std::string& type) const; | 310 const std::string& type) const; |
| 330 | 311 |
| 331 base::TimeDelta ConnectionTimeout() const { | 312 base::TimeDelta ConnectionTimeout() const { |
| 332 return connect_job_factory_->ConnectionTimeout(); | 313 return connect_job_factory_->ConnectionTimeout(); |
| 333 } | 314 } |
| 334 | 315 |
| 335 static bool connect_backup_jobs_enabled(); | 316 static bool connect_backup_jobs_enabled(); |
| 336 static bool set_connect_backup_jobs_enabled(bool enabled); | 317 static bool set_connect_backup_jobs_enabled(bool enabled); |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 470 void IncrementIdleCount(); | 451 void IncrementIdleCount(); |
| 471 void DecrementIdleCount(); | 452 void DecrementIdleCount(); |
| 472 | 453 |
| 473 // Start cleanup timer for idle sockets. | 454 // Start cleanup timer for idle sockets. |
| 474 void StartIdleSocketTimer(); | 455 void StartIdleSocketTimer(); |
| 475 | 456 |
| 476 // Scans the group map for groups which have an available socket slot and | 457 // Scans the group map for groups which have an available socket slot and |
| 477 // at least one pending request. Returns true if any groups are stalled, and | 458 // at least one pending request. Returns true if any groups are stalled, and |
| 478 // if so, fills |group| and |group_name| with data of the stalled group | 459 // if so, fills |group| and |group_name| with data of the stalled group |
| 479 // having highest priority. | 460 // having highest priority. |
| 480 bool FindTopStalledGroup(Group** group, std::string* group_name) const; | 461 bool FindTopStalledGroup(Group** group, std::string* group_name); |
| 481 | 462 |
| 482 // Called when timer_ fires. This method scans the idle sockets removing | 463 // Called when timer_ fires. This method scans the idle sockets removing |
| 483 // sockets that timed out or can't be reused. | 464 // sockets that timed out or can't be reused. |
| 484 void OnCleanupTimerFired() { | 465 void OnCleanupTimerFired() { |
| 485 CleanupIdleSockets(false); | 466 CleanupIdleSockets(false); |
| 486 } | 467 } |
| 487 | 468 |
| 488 // Removes |job| from |connect_job_set_|. Also updates |group| if non-NULL. | 469 // Removes |job| from |connect_job_set_|. Also updates |group| if non-NULL. |
| 489 void RemoveConnectJob(ConnectJob* job, Group* group); | 470 void RemoveConnectJob(ConnectJob* job, Group* group); |
| 490 | 471 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 522 int RequestSocketInternal(const std::string& group_name, | 503 int RequestSocketInternal(const std::string& group_name, |
| 523 const Request* request); | 504 const Request* request); |
| 524 | 505 |
| 525 // Assigns an idle socket for the group to the request. | 506 // Assigns an idle socket for the group to the request. |
| 526 // Returns |true| if an idle socket is available, false otherwise. | 507 // Returns |true| if an idle socket is available, false otherwise. |
| 527 bool AssignIdleSocketToGroup(const Request* request, Group* group); | 508 bool AssignIdleSocketToGroup(const Request* request, Group* group); |
| 528 | 509 |
| 529 static void LogBoundConnectJobToRequest( | 510 static void LogBoundConnectJobToRequest( |
| 530 const NetLog::Source& connect_job_source, const Request* request); | 511 const NetLog::Source& connect_job_source, const Request* request); |
| 531 | 512 |
| 513 // Closes one idle socket. Picks the first one encountered. |
| 514 // TODO(willchan): Consider a better algorithm for doing this. Perhaps we |
| 515 // should keep an ordered list of idle sockets, and close them in order. |
| 516 // Requires maintaining more state. It's not clear if it's worth it since |
| 517 // I'm not sure if we hit this situation often. |
| 518 void CloseOneIdleSocket(); |
| 519 |
| 532 // Same as CloseOneIdleSocket() except it won't close an idle socket in | 520 // Same as CloseOneIdleSocket() except it won't close an idle socket in |
| 533 // |group|. If |group| is NULL, it is ignored. Returns true if it closed a | 521 // |group|. If |group| is NULL, it is ignored. Returns true if it closed a |
| 534 // socket. | 522 // socket. |
| 535 bool CloseOneIdleSocketExceptInGroup(const Group* group); | 523 bool CloseOneIdleSocketExceptInGroup(const Group* group); |
| 536 | 524 |
| 537 // Checks if there are stalled socket groups that should be notified | 525 // Checks if there are stalled socket groups that should be notified |
| 538 // for possible wakeup. | 526 // for possible wakeup. |
| 539 void CheckForStalledSocketGroups(); | 527 void CheckForStalledSocketGroups(); |
| 540 | 528 |
| 541 // Posts a task to call InvokeUserCallback() on the next iteration through the | 529 // Posts a task to call InvokeUserCallback() on the next iteration through the |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 586 const scoped_ptr<ConnectJobFactory> connect_job_factory_; | 574 const scoped_ptr<ConnectJobFactory> connect_job_factory_; |
| 587 | 575 |
| 588 // TODO(vandebo) Remove when backup jobs move to TransportClientSocketPool | 576 // TODO(vandebo) Remove when backup jobs move to TransportClientSocketPool |
| 589 bool connect_backup_jobs_enabled_; | 577 bool connect_backup_jobs_enabled_; |
| 590 | 578 |
| 591 // A unique id for the pool. It gets incremented every time we Flush() the | 579 // A unique id for the pool. It gets incremented every time we Flush() the |
| 592 // pool. This is so that when sockets get released back to the pool, we can | 580 // pool. This is so that when sockets get released back to the pool, we can |
| 593 // make sure that they are discarded rather than reused. | 581 // make sure that they are discarded rather than reused. |
| 594 int pool_generation_number_; | 582 int pool_generation_number_; |
| 595 | 583 |
| 596 std::set<LayeredPool*> higher_layer_pools_; | |
| 597 | |
| 598 base::WeakPtrFactory<ClientSocketPoolBaseHelper> weak_factory_; | 584 base::WeakPtrFactory<ClientSocketPoolBaseHelper> weak_factory_; |
| 599 | 585 |
| 600 DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBaseHelper); | 586 DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBaseHelper); |
| 601 }; | 587 }; |
| 602 | 588 |
| 603 } // namespace internal | 589 } // namespace internal |
| 604 | 590 |
| 605 template <typename SocketParams> | 591 template <typename SocketParams> |
| 606 class ClientSocketPoolBase { | 592 class ClientSocketPoolBase { |
| 607 public: | 593 public: |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 654 base::TimeDelta used_idle_socket_timeout, | 640 base::TimeDelta used_idle_socket_timeout, |
| 655 ConnectJobFactory* connect_job_factory) | 641 ConnectJobFactory* connect_job_factory) |
| 656 : histograms_(histograms), | 642 : histograms_(histograms), |
| 657 helper_(max_sockets, max_sockets_per_group, | 643 helper_(max_sockets, max_sockets_per_group, |
| 658 unused_idle_socket_timeout, used_idle_socket_timeout, | 644 unused_idle_socket_timeout, used_idle_socket_timeout, |
| 659 new ConnectJobFactoryAdaptor(connect_job_factory)) {} | 645 new ConnectJobFactoryAdaptor(connect_job_factory)) {} |
| 660 | 646 |
| 661 virtual ~ClientSocketPoolBase() {} | 647 virtual ~ClientSocketPoolBase() {} |
| 662 | 648 |
| 663 // These member functions simply forward to ClientSocketPoolBaseHelper. | 649 // These member functions simply forward to ClientSocketPoolBaseHelper. |
| 664 void AddLayeredPool(LayeredPool* pool) { | |
| 665 helper_.AddLayeredPool(pool); | |
| 666 } | |
| 667 | |
| 668 void RemoveLayeredPool(LayeredPool* pool) { | |
| 669 helper_.RemoveLayeredPool(pool); | |
| 670 } | |
| 671 | 650 |
| 672 // RequestSocket bundles up the parameters into a Request and then forwards to | 651 // RequestSocket bundles up the parameters into a Request and then forwards to |
| 673 // ClientSocketPoolBaseHelper::RequestSocket(). | 652 // ClientSocketPoolBaseHelper::RequestSocket(). |
| 674 int RequestSocket(const std::string& group_name, | 653 int RequestSocket(const std::string& group_name, |
| 675 const scoped_refptr<SocketParams>& params, | 654 const scoped_refptr<SocketParams>& params, |
| 676 RequestPriority priority, | 655 RequestPriority priority, |
| 677 ClientSocketHandle* handle, | 656 ClientSocketHandle* handle, |
| 678 const CompletionCallback& callback, | 657 const CompletionCallback& callback, |
| 679 const BoundNetLog& net_log) { | 658 const BoundNetLog& net_log) { |
| 680 Request* request = | 659 Request* request = |
| (...skipping 24 matching lines...) Expand all Loading... |
| 705 void CancelRequest(const std::string& group_name, | 684 void CancelRequest(const std::string& group_name, |
| 706 ClientSocketHandle* handle) { | 685 ClientSocketHandle* handle) { |
| 707 return helper_.CancelRequest(group_name, handle); | 686 return helper_.CancelRequest(group_name, handle); |
| 708 } | 687 } |
| 709 | 688 |
| 710 void ReleaseSocket(const std::string& group_name, StreamSocket* socket, | 689 void ReleaseSocket(const std::string& group_name, StreamSocket* socket, |
| 711 int id) { | 690 int id) { |
| 712 return helper_.ReleaseSocket(group_name, socket, id); | 691 return helper_.ReleaseSocket(group_name, socket, id); |
| 713 } | 692 } |
| 714 | 693 |
| 715 void Flush() { helper_.Flush(); } | |
| 716 | |
| 717 bool IsStalled() const { return helper_.IsStalled(); } | |
| 718 | |
| 719 void CloseIdleSockets() { return helper_.CloseIdleSockets(); } | 694 void CloseIdleSockets() { return helper_.CloseIdleSockets(); } |
| 720 | 695 |
| 721 int idle_socket_count() const { return helper_.idle_socket_count(); } | 696 int idle_socket_count() const { return helper_.idle_socket_count(); } |
| 722 | 697 |
| 723 int IdleSocketCountInGroup(const std::string& group_name) const { | 698 int IdleSocketCountInGroup(const std::string& group_name) const { |
| 724 return helper_.IdleSocketCountInGroup(group_name); | 699 return helper_.IdleSocketCountInGroup(group_name); |
| 725 } | 700 } |
| 726 | 701 |
| 727 LoadState GetLoadState(const std::string& group_name, | 702 LoadState GetLoadState(const std::string& group_name, |
| 728 const ClientSocketHandle* handle) const { | 703 const ClientSocketHandle* handle) const { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 757 base::TimeDelta ConnectionTimeout() const { | 732 base::TimeDelta ConnectionTimeout() const { |
| 758 return helper_.ConnectionTimeout(); | 733 return helper_.ConnectionTimeout(); |
| 759 } | 734 } |
| 760 | 735 |
| 761 ClientSocketPoolHistograms* histograms() const { | 736 ClientSocketPoolHistograms* histograms() const { |
| 762 return histograms_; | 737 return histograms_; |
| 763 } | 738 } |
| 764 | 739 |
| 765 void EnableConnectBackupJobs() { helper_.EnableConnectBackupJobs(); } | 740 void EnableConnectBackupJobs() { helper_.EnableConnectBackupJobs(); } |
| 766 | 741 |
| 767 bool CloseOneIdleSocket() { return helper_.CloseOneIdleSocket(); } | 742 void Flush() { helper_.Flush(); } |
| 768 | |
| 769 bool CloseOneIdleConnectionInLayeredPool() { | |
| 770 return helper_.CloseOneIdleConnectionInLayeredPool(); | |
| 771 } | |
| 772 | 743 |
| 773 private: | 744 private: |
| 774 // This adaptor class exists to bridge the | 745 // This adaptor class exists to bridge the |
| 775 // internal::ClientSocketPoolBaseHelper::ConnectJobFactory and | 746 // internal::ClientSocketPoolBaseHelper::ConnectJobFactory and |
| 776 // ClientSocketPoolBase::ConnectJobFactory types, allowing clients to use the | 747 // ClientSocketPoolBase::ConnectJobFactory types, allowing clients to use the |
| 777 // typesafe ClientSocketPoolBase::ConnectJobFactory, rather than having to | 748 // typesafe ClientSocketPoolBase::ConnectJobFactory, rather than having to |
| 778 // static_cast themselves. | 749 // static_cast themselves. |
| 779 class ConnectJobFactoryAdaptor | 750 class ConnectJobFactoryAdaptor |
| 780 : public internal::ClientSocketPoolBaseHelper::ConnectJobFactory { | 751 : public internal::ClientSocketPoolBaseHelper::ConnectJobFactory { |
| 781 public: | 752 public: |
| (...skipping 23 matching lines...) Expand all Loading... |
| 805 // Histograms for the pool | 776 // Histograms for the pool |
| 806 ClientSocketPoolHistograms* const histograms_; | 777 ClientSocketPoolHistograms* const histograms_; |
| 807 internal::ClientSocketPoolBaseHelper helper_; | 778 internal::ClientSocketPoolBaseHelper helper_; |
| 808 | 779 |
| 809 DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBase); | 780 DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBase); |
| 810 }; | 781 }; |
| 811 | 782 |
| 812 } // namespace net | 783 } // namespace net |
| 813 | 784 |
| 814 #endif // NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_ | 785 #endif // NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_ |
| OLD | NEW |