OLD | NEW |
1 // Copyright (c) 2012 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) |
(...skipping 10 matching lines...) Expand all Loading... |
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 25 matching lines...) Expand all Loading... |
308 // by kCleanupInterval are cleaned up using a timer. Otherwise they are | 299 // by kCleanupInterval are cleaned up using a timer. Otherwise they are |
309 // closed next time client makes a request. This may reduce network | 300 // closed next time client makes a request. This may reduce network |
310 // activity and power consumption. | 301 // activity and power consumption. |
311 static bool cleanup_timer_enabled(); | 302 static bool cleanup_timer_enabled(); |
312 static bool set_cleanup_timer_enabled(bool enabled); | 303 static bool set_cleanup_timer_enabled(bool enabled); |
313 | 304 |
314 // Closes all idle sockets if |force| is true. Else, only closes idle | 305 // Closes all idle sockets if |force| is true. Else, only closes idle |
315 // sockets that timed out or can't be reused. Made public for testing. | 306 // sockets that timed out or can't be reused. Made public for testing. |
316 void CleanupIdleSockets(bool force); | 307 void CleanupIdleSockets(bool force); |
317 | 308 |
318 // Closes one idle socket. Picks the first one encountered. | |
319 // TODO(willchan): Consider a better algorithm for doing this. Perhaps we | |
320 // should keep an ordered list of idle sockets, and close them in order. | |
321 // Requires maintaining more state. It's not clear if it's worth it since | |
322 // I'm not sure if we hit this situation often. | |
323 bool CloseOneIdleSocket(); | |
324 | |
325 // Checks layered pools to see if they can close an idle connection. | |
326 bool CloseOneIdleConnectionInLayeredPool(); | |
327 | |
328 // See ClientSocketPool::GetInfoAsValue for documentation on this function. | 309 // See ClientSocketPool::GetInfoAsValue for documentation on this function. |
329 base::DictionaryValue* GetInfoAsValue(const std::string& name, | 310 base::DictionaryValue* GetInfoAsValue(const std::string& name, |
330 const std::string& type) const; | 311 const std::string& type) const; |
331 | 312 |
332 base::TimeDelta ConnectionTimeout() const { | 313 base::TimeDelta ConnectionTimeout() const { |
333 return connect_job_factory_->ConnectionTimeout(); | 314 return connect_job_factory_->ConnectionTimeout(); |
334 } | 315 } |
335 | 316 |
336 static bool connect_backup_jobs_enabled(); | 317 static bool connect_backup_jobs_enabled(); |
337 static bool set_connect_backup_jobs_enabled(bool enabled); | 318 static bool set_connect_backup_jobs_enabled(bool enabled); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
383 | 364 |
384 bool HasAvailableSocketSlot(int max_sockets_per_group) const { | 365 bool HasAvailableSocketSlot(int max_sockets_per_group) const { |
385 return NumActiveSocketSlots() < max_sockets_per_group; | 366 return NumActiveSocketSlots() < max_sockets_per_group; |
386 } | 367 } |
387 | 368 |
388 int NumActiveSocketSlots() const { | 369 int NumActiveSocketSlots() const { |
389 return active_socket_count_ + static_cast<int>(jobs_.size()) + | 370 return active_socket_count_ + static_cast<int>(jobs_.size()) + |
390 static_cast<int>(idle_sockets_.size()); | 371 static_cast<int>(idle_sockets_.size()); |
391 } | 372 } |
392 | 373 |
393 bool IsStalledOnPoolMaxSockets(int max_sockets_per_group) const { | 374 bool IsStalled(int max_sockets_per_group) const { |
394 return HasAvailableSocketSlot(max_sockets_per_group) && | 375 return HasAvailableSocketSlot(max_sockets_per_group) && |
395 pending_requests_.size() > jobs_.size(); | 376 pending_requests_.size() > jobs_.size(); |
396 } | 377 } |
397 | 378 |
398 RequestPriority TopPendingPriority() const { | 379 RequestPriority TopPendingPriority() const { |
399 return pending_requests_.front()->priority(); | 380 return pending_requests_.front()->priority(); |
400 } | 381 } |
401 | 382 |
402 bool HasBackupJob() const { return weak_factory_.HasWeakPtrs(); } | 383 bool HasBackupJob() const { return weak_factory_.HasWeakPtrs(); } |
403 | 384 |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
469 | 450 |
470 // Called when the number of idle sockets changes. | 451 // Called when the number of idle sockets changes. |
471 void IncrementIdleCount(); | 452 void IncrementIdleCount(); |
472 void DecrementIdleCount(); | 453 void DecrementIdleCount(); |
473 | 454 |
474 // Start cleanup timer for idle sockets. | 455 // Start cleanup timer for idle sockets. |
475 void StartIdleSocketTimer(); | 456 void StartIdleSocketTimer(); |
476 | 457 |
477 // Scans the group map for groups which have an available socket slot and | 458 // Scans the group map for groups which have an available socket slot and |
478 // at least one pending request. Returns true if any groups are stalled, and | 459 // at least one pending request. Returns true if any groups are stalled, and |
479 // if so (and if both |group| and |group_name| are not NULL), fills |group| | 460 // if so, fills |group| and |group_name| with data of the stalled group |
480 // and |group_name| with data of the stalled group having highest priority. | 461 // having highest priority. |
481 bool FindTopStalledGroup(Group** group, std::string* group_name) const; | 462 bool FindTopStalledGroup(Group** group, std::string* group_name); |
482 | 463 |
483 // Called when timer_ fires. This method scans the idle sockets removing | 464 // Called when timer_ fires. This method scans the idle sockets removing |
484 // sockets that timed out or can't be reused. | 465 // sockets that timed out or can't be reused. |
485 void OnCleanupTimerFired() { | 466 void OnCleanupTimerFired() { |
486 CleanupIdleSockets(false); | 467 CleanupIdleSockets(false); |
487 } | 468 } |
488 | 469 |
489 // Removes |job| from |connect_job_set_|. Also updates |group| if non-NULL. | 470 // Removes |job| from |connect_job_set_|. Also updates |group| if non-NULL. |
490 void RemoveConnectJob(ConnectJob* job, Group* group); | 471 void RemoveConnectJob(ConnectJob* job, Group* group); |
491 | 472 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
523 int RequestSocketInternal(const std::string& group_name, | 504 int RequestSocketInternal(const std::string& group_name, |
524 const Request* request); | 505 const Request* request); |
525 | 506 |
526 // Assigns an idle socket for the group to the request. | 507 // Assigns an idle socket for the group to the request. |
527 // Returns |true| if an idle socket is available, false otherwise. | 508 // Returns |true| if an idle socket is available, false otherwise. |
528 bool AssignIdleSocketToGroup(const Request* request, Group* group); | 509 bool AssignIdleSocketToGroup(const Request* request, Group* group); |
529 | 510 |
530 static void LogBoundConnectJobToRequest( | 511 static void LogBoundConnectJobToRequest( |
531 const NetLog::Source& connect_job_source, const Request* request); | 512 const NetLog::Source& connect_job_source, const Request* request); |
532 | 513 |
| 514 // Closes one idle socket. Picks the first one encountered. |
| 515 // TODO(willchan): Consider a better algorithm for doing this. Perhaps we |
| 516 // should keep an ordered list of idle sockets, and close them in order. |
| 517 // Requires maintaining more state. It's not clear if it's worth it since |
| 518 // I'm not sure if we hit this situation often. |
| 519 void CloseOneIdleSocket(); |
| 520 |
533 // Same as CloseOneIdleSocket() except it won't close an idle socket in | 521 // Same as CloseOneIdleSocket() except it won't close an idle socket in |
534 // |group|. If |group| is NULL, it is ignored. Returns true if it closed a | 522 // |group|. If |group| is NULL, it is ignored. Returns true if it closed a |
535 // socket. | 523 // socket. |
536 bool CloseOneIdleSocketExceptInGroup(const Group* group); | 524 bool CloseOneIdleSocketExceptInGroup(const Group* group); |
537 | 525 |
538 // Checks if there are stalled socket groups that should be notified | 526 // Checks if there are stalled socket groups that should be notified |
539 // for possible wakeup. | 527 // for possible wakeup. |
540 void CheckForStalledSocketGroups(); | 528 void CheckForStalledSocketGroups(); |
541 | 529 |
542 // Posts a task to call InvokeUserCallback() on the next iteration through the | 530 // 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... |
587 const scoped_ptr<ConnectJobFactory> connect_job_factory_; | 575 const scoped_ptr<ConnectJobFactory> connect_job_factory_; |
588 | 576 |
589 // TODO(vandebo) Remove when backup jobs move to TransportClientSocketPool | 577 // TODO(vandebo) Remove when backup jobs move to TransportClientSocketPool |
590 bool connect_backup_jobs_enabled_; | 578 bool connect_backup_jobs_enabled_; |
591 | 579 |
592 // A unique id for the pool. It gets incremented every time we Flush() the | 580 // A unique id for the pool. It gets incremented every time we Flush() the |
593 // pool. This is so that when sockets get released back to the pool, we can | 581 // pool. This is so that when sockets get released back to the pool, we can |
594 // make sure that they are discarded rather than reused. | 582 // make sure that they are discarded rather than reused. |
595 int pool_generation_number_; | 583 int pool_generation_number_; |
596 | 584 |
597 std::set<LayeredPool*> higher_layer_pools_; | |
598 | |
599 base::WeakPtrFactory<ClientSocketPoolBaseHelper> weak_factory_; | 585 base::WeakPtrFactory<ClientSocketPoolBaseHelper> weak_factory_; |
600 | 586 |
601 DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBaseHelper); | 587 DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBaseHelper); |
602 }; | 588 }; |
603 | 589 |
604 } // namespace internal | 590 } // namespace internal |
605 | 591 |
606 template <typename SocketParams> | 592 template <typename SocketParams> |
607 class ClientSocketPoolBase { | 593 class ClientSocketPoolBase { |
608 public: | 594 public: |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
655 base::TimeDelta used_idle_socket_timeout, | 641 base::TimeDelta used_idle_socket_timeout, |
656 ConnectJobFactory* connect_job_factory) | 642 ConnectJobFactory* connect_job_factory) |
657 : histograms_(histograms), | 643 : histograms_(histograms), |
658 helper_(max_sockets, max_sockets_per_group, | 644 helper_(max_sockets, max_sockets_per_group, |
659 unused_idle_socket_timeout, used_idle_socket_timeout, | 645 unused_idle_socket_timeout, used_idle_socket_timeout, |
660 new ConnectJobFactoryAdaptor(connect_job_factory)) {} | 646 new ConnectJobFactoryAdaptor(connect_job_factory)) {} |
661 | 647 |
662 virtual ~ClientSocketPoolBase() {} | 648 virtual ~ClientSocketPoolBase() {} |
663 | 649 |
664 // These member functions simply forward to ClientSocketPoolBaseHelper. | 650 // These member functions simply forward to ClientSocketPoolBaseHelper. |
665 void AddLayeredPool(LayeredPool* pool) { | |
666 helper_.AddLayeredPool(pool); | |
667 } | |
668 | |
669 void RemoveLayeredPool(LayeredPool* pool) { | |
670 helper_.RemoveLayeredPool(pool); | |
671 } | |
672 | 651 |
673 // RequestSocket bundles up the parameters into a Request and then forwards to | 652 // RequestSocket bundles up the parameters into a Request and then forwards to |
674 // ClientSocketPoolBaseHelper::RequestSocket(). | 653 // ClientSocketPoolBaseHelper::RequestSocket(). |
675 int RequestSocket(const std::string& group_name, | 654 int RequestSocket(const std::string& group_name, |
676 const scoped_refptr<SocketParams>& params, | 655 const scoped_refptr<SocketParams>& params, |
677 RequestPriority priority, | 656 RequestPriority priority, |
678 ClientSocketHandle* handle, | 657 ClientSocketHandle* handle, |
679 const CompletionCallback& callback, | 658 const CompletionCallback& callback, |
680 const BoundNetLog& net_log) { | 659 const BoundNetLog& net_log) { |
681 Request* request = | 660 Request* request = |
(...skipping 24 matching lines...) Expand all Loading... |
706 void CancelRequest(const std::string& group_name, | 685 void CancelRequest(const std::string& group_name, |
707 ClientSocketHandle* handle) { | 686 ClientSocketHandle* handle) { |
708 return helper_.CancelRequest(group_name, handle); | 687 return helper_.CancelRequest(group_name, handle); |
709 } | 688 } |
710 | 689 |
711 void ReleaseSocket(const std::string& group_name, StreamSocket* socket, | 690 void ReleaseSocket(const std::string& group_name, StreamSocket* socket, |
712 int id) { | 691 int id) { |
713 return helper_.ReleaseSocket(group_name, socket, id); | 692 return helper_.ReleaseSocket(group_name, socket, id); |
714 } | 693 } |
715 | 694 |
716 void Flush() { helper_.Flush(); } | |
717 | |
718 bool IsStalled() const { return helper_.IsStalled(); } | |
719 | |
720 void CloseIdleSockets() { return helper_.CloseIdleSockets(); } | 695 void CloseIdleSockets() { return helper_.CloseIdleSockets(); } |
721 | 696 |
722 int idle_socket_count() const { return helper_.idle_socket_count(); } | 697 int idle_socket_count() const { return helper_.idle_socket_count(); } |
723 | 698 |
724 int IdleSocketCountInGroup(const std::string& group_name) const { | 699 int IdleSocketCountInGroup(const std::string& group_name) const { |
725 return helper_.IdleSocketCountInGroup(group_name); | 700 return helper_.IdleSocketCountInGroup(group_name); |
726 } | 701 } |
727 | 702 |
728 LoadState GetLoadState(const std::string& group_name, | 703 LoadState GetLoadState(const std::string& group_name, |
729 const ClientSocketHandle* handle) const { | 704 const ClientSocketHandle* handle) const { |
(...skipping 28 matching lines...) Expand all Loading... |
758 base::TimeDelta ConnectionTimeout() const { | 733 base::TimeDelta ConnectionTimeout() const { |
759 return helper_.ConnectionTimeout(); | 734 return helper_.ConnectionTimeout(); |
760 } | 735 } |
761 | 736 |
762 ClientSocketPoolHistograms* histograms() const { | 737 ClientSocketPoolHistograms* histograms() const { |
763 return histograms_; | 738 return histograms_; |
764 } | 739 } |
765 | 740 |
766 void EnableConnectBackupJobs() { helper_.EnableConnectBackupJobs(); } | 741 void EnableConnectBackupJobs() { helper_.EnableConnectBackupJobs(); } |
767 | 742 |
768 bool CloseOneIdleSocket() { return helper_.CloseOneIdleSocket(); } | 743 void Flush() { helper_.Flush(); } |
769 | |
770 bool CloseOneIdleConnectionInLayeredPool() { | |
771 return helper_.CloseOneIdleConnectionInLayeredPool(); | |
772 } | |
773 | 744 |
774 private: | 745 private: |
775 // This adaptor class exists to bridge the | 746 // This adaptor class exists to bridge the |
776 // internal::ClientSocketPoolBaseHelper::ConnectJobFactory and | 747 // internal::ClientSocketPoolBaseHelper::ConnectJobFactory and |
777 // ClientSocketPoolBase::ConnectJobFactory types, allowing clients to use the | 748 // ClientSocketPoolBase::ConnectJobFactory types, allowing clients to use the |
778 // typesafe ClientSocketPoolBase::ConnectJobFactory, rather than having to | 749 // typesafe ClientSocketPoolBase::ConnectJobFactory, rather than having to |
779 // static_cast themselves. | 750 // static_cast themselves. |
780 class ConnectJobFactoryAdaptor | 751 class ConnectJobFactoryAdaptor |
781 : public internal::ClientSocketPoolBaseHelper::ConnectJobFactory { | 752 : public internal::ClientSocketPoolBaseHelper::ConnectJobFactory { |
782 public: | 753 public: |
(...skipping 23 matching lines...) Expand all Loading... |
806 // Histograms for the pool | 777 // Histograms for the pool |
807 ClientSocketPoolHistograms* const histograms_; | 778 ClientSocketPoolHistograms* const histograms_; |
808 internal::ClientSocketPoolBaseHelper helper_; | 779 internal::ClientSocketPoolBaseHelper helper_; |
809 | 780 |
810 DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBase); | 781 DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBase); |
811 }; | 782 }; |
812 | 783 |
813 } // namespace net | 784 } // namespace net |
814 | 785 |
815 #endif // NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_ | 786 #endif // NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_ |
OLD | NEW |