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 12 matching lines...) Expand all Loading... |
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 | 31 |
32 #include "base/basictypes.h" | 32 #include "base/basictypes.h" |
| 33 #include "base/prebind.h" |
33 #include "base/ref_counted.h" | 34 #include "base/ref_counted.h" |
34 #include "base/scoped_ptr.h" | 35 #include "base/scoped_ptr.h" |
35 #include "base/task.h" | 36 #include "base/task.h" |
36 #include "base/time.h" | 37 #include "base/time.h" |
37 #include "base/timer.h" | 38 #include "base/timer.h" |
38 #include "net/base/address_list.h" | 39 #include "net/base/address_list.h" |
39 #include "net/base/completion_callback.h" | 40 #include "net/base/completion_callback.h" |
40 #include "net/base/load_states.h" | 41 #include "net/base/load_states.h" |
41 #include "net/base/net_errors.h" | 42 #include "net/base/net_errors.h" |
42 #include "net/base/net_log.h" | 43 #include "net/base/net_log.h" |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
158 : public ConnectJob::Delegate, | 159 : public ConnectJob::Delegate, |
159 public NetworkChangeNotifier::Observer { | 160 public NetworkChangeNotifier::Observer { |
160 public: | 161 public: |
161 // Used to specify specific behavior for the ClientSocketPool. | 162 // Used to specify specific behavior for the ClientSocketPool. |
162 enum Flag { | 163 enum Flag { |
163 NORMAL = 0, // Normal behavior. | 164 NORMAL = 0, // Normal behavior. |
164 NO_IDLE_SOCKETS = 0x1, // Do not return an idle socket. Create a new one. | 165 NO_IDLE_SOCKETS = 0x1, // Do not return an idle socket. Create a new one. |
165 }; | 166 }; |
166 | 167 |
167 typedef uint32 Flags; | 168 typedef uint32 Flags; |
| 169 typedef base::Thunk<void(int)> Tr1CompletionCallback; |
168 | 170 |
169 class Request { | 171 class Request { |
170 public: | 172 public: |
171 Request(ClientSocketHandle* handle, | 173 Request(ClientSocketHandle* handle, |
172 CompletionCallback* callback, | 174 Tr1CompletionCallback callback, |
173 RequestPriority priority, | 175 RequestPriority priority, |
174 Flags flags, | 176 Flags flags, |
175 const BoundNetLog& net_log); | 177 const BoundNetLog& net_log); |
176 | 178 |
177 virtual ~Request(); | 179 virtual ~Request(); |
178 | 180 |
179 ClientSocketHandle* handle() const { return handle_; } | 181 ClientSocketHandle* handle() const { return handle_; } |
180 CompletionCallback* callback() const { return callback_; } | 182 Tr1CompletionCallback callback() const { return callback_; } |
181 RequestPriority priority() const { return priority_; } | 183 RequestPriority priority() const { return priority_; } |
182 Flags flags() const { return flags_; } | 184 Flags flags() const { return flags_; } |
183 const BoundNetLog& net_log() const { return net_log_; } | 185 const BoundNetLog& net_log() const { return net_log_; } |
184 | 186 |
185 private: | 187 private: |
186 ClientSocketHandle* const handle_; | 188 ClientSocketHandle* const handle_; |
187 CompletionCallback* const callback_; | 189 Tr1CompletionCallback const callback_; |
188 const RequestPriority priority_; | 190 const RequestPriority priority_; |
189 const Flags flags_; | 191 const Flags flags_; |
190 BoundNetLog net_log_; | 192 BoundNetLog net_log_; |
191 | 193 |
192 DISALLOW_COPY_AND_ASSIGN(Request); | 194 DISALLOW_COPY_AND_ASSIGN(Request); |
193 }; | 195 }; |
194 | 196 |
195 class ConnectJobFactory { | 197 class ConnectJobFactory { |
196 public: | 198 public: |
197 ConnectJobFactory() {} | 199 ConnectJobFactory() {} |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
339 | 341 |
340 bool IsStalled(int max_sockets_per_group) const { | 342 bool IsStalled(int max_sockets_per_group) const { |
341 return HasAvailableSocketSlot(max_sockets_per_group) && | 343 return HasAvailableSocketSlot(max_sockets_per_group) && |
342 pending_requests_.size() > jobs_.size(); | 344 pending_requests_.size() > jobs_.size(); |
343 } | 345 } |
344 | 346 |
345 RequestPriority TopPendingPriority() const { | 347 RequestPriority TopPendingPriority() const { |
346 return pending_requests_.front()->priority(); | 348 return pending_requests_.front()->priority(); |
347 } | 349 } |
348 | 350 |
349 bool HasBackupJob() const { return !method_factory_.empty(); } | 351 bool HasBackupJob() const { return !thunk_canceller_.empty(); } |
350 | 352 |
351 void CleanupBackupJob() { | 353 void CleanupBackupJob() { |
352 method_factory_.RevokeAll(); | 354 thunk_canceller_.RevokeAll(); |
353 } | 355 } |
354 | 356 |
355 // Set a timer to create a backup socket if it takes too long to create one. | 357 // Set a timer to create a backup socket if it takes too long to create one. |
356 void StartBackupSocketTimer(const std::string& group_name, | 358 void StartBackupSocketTimer(const std::string& group_name, |
357 ClientSocketPoolBaseHelper* pool); | 359 ClientSocketPoolBaseHelper* pool); |
358 | 360 |
359 // Searches |jobs_| to see if there's a preconnect ConnectJob, and if so, | 361 // Searches |jobs_| to see if there's a preconnect ConnectJob, and if so, |
360 // uses it. Returns true on success. Otherwise, returns false. | 362 // uses it. Returns true on success. Otherwise, returns false. |
361 bool TryToUsePreconnectConnectJob(); | 363 bool TryToUsePreconnectConnectJob(); |
362 | 364 |
(...skipping 15 matching lines...) Expand all Loading... |
378 // Called when the backup socket timer fires. | 380 // Called when the backup socket timer fires. |
379 void OnBackupSocketTimerFired( | 381 void OnBackupSocketTimerFired( |
380 std::string group_name, | 382 std::string group_name, |
381 ClientSocketPoolBaseHelper* pool); | 383 ClientSocketPoolBaseHelper* pool); |
382 | 384 |
383 std::list<IdleSocket> idle_sockets_; | 385 std::list<IdleSocket> idle_sockets_; |
384 std::set<ConnectJob*> jobs_; | 386 std::set<ConnectJob*> jobs_; |
385 RequestQueue pending_requests_; | 387 RequestQueue pending_requests_; |
386 int active_socket_count_; // number of active sockets used by clients | 388 int active_socket_count_; // number of active sockets used by clients |
387 // A factory to pin the backup_job tasks. | 389 // A factory to pin the backup_job tasks. |
388 ScopedRunnableMethodFactory<Group> method_factory_; | 390 base::ThunkCanceller thunk_canceller_; |
389 }; | 391 }; |
390 | 392 |
391 typedef std::map<std::string, Group*> GroupMap; | 393 typedef std::map<std::string, Group*> GroupMap; |
392 | 394 |
393 typedef std::set<ConnectJob*> ConnectJobSet; | 395 typedef std::set<ConnectJob*> ConnectJobSet; |
394 | 396 |
395 struct CallbackResultPair { | 397 struct CallbackResultPair { |
396 CallbackResultPair() : callback(NULL), result(OK) {} | 398 CallbackResultPair() : callback(NULL), result(OK) {} |
397 CallbackResultPair(CompletionCallback* callback_in, int result_in) | 399 CallbackResultPair(Tr1CompletionCallback callback_in, int result_in) |
398 : callback(callback_in), result(result_in) {} | 400 : callback(callback_in), result(result_in) {} |
399 | 401 |
400 CompletionCallback* callback; | 402 Tr1CompletionCallback callback; |
401 int result; | 403 int result; |
402 }; | 404 }; |
403 | 405 |
404 typedef std::map<const ClientSocketHandle*, CallbackResultPair> | 406 typedef std::map<const ClientSocketHandle*, CallbackResultPair> |
405 PendingCallbackMap; | 407 PendingCallbackMap; |
406 | 408 |
407 static void InsertRequestIntoQueue(const Request* r, | 409 static void InsertRequestIntoQueue(const Request* r, |
408 RequestQueue* pending_requests); | 410 RequestQueue* pending_requests); |
409 static const Request* RemoveRequestFromQueue(RequestQueue::iterator it, | 411 static const Request* RemoveRequestFromQueue(RequestQueue::iterator it, |
410 Group* group); | 412 Group* group); |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
486 bool CloseOneIdleSocketExceptInGroup(const Group* group); | 488 bool CloseOneIdleSocketExceptInGroup(const Group* group); |
487 | 489 |
488 // Checks if there are stalled socket groups that should be notified | 490 // Checks if there are stalled socket groups that should be notified |
489 // for possible wakeup. | 491 // for possible wakeup. |
490 void CheckForStalledSocketGroups(); | 492 void CheckForStalledSocketGroups(); |
491 | 493 |
492 // Posts a task to call InvokeUserCallback() on the next iteration through the | 494 // Posts a task to call InvokeUserCallback() on the next iteration through the |
493 // current message loop. Inserts |callback| into |pending_callback_map_|, | 495 // current message loop. Inserts |callback| into |pending_callback_map_|, |
494 // keyed by |handle|. | 496 // keyed by |handle|. |
495 void InvokeUserCallbackLater( | 497 void InvokeUserCallbackLater( |
496 ClientSocketHandle* handle, CompletionCallback* callback, int rv); | 498 ClientSocketHandle* handle, Tr1CompletionCallback callback, int rv); |
497 | 499 |
498 // Invokes the user callback for |handle|. By the time this task has run, | 500 // Invokes the user callback for |handle|. By the time this task has run, |
499 // it's possible that the request has been cancelled, so |handle| may not | 501 // it's possible that the request has been cancelled, so |handle| may not |
500 // exist in |pending_callback_map_|. We look up the callback and result code | 502 // exist in |pending_callback_map_|. We look up the callback and result code |
501 // in |pending_callback_map_|. | 503 // in |pending_callback_map_|. |
502 void InvokeUserCallback(ClientSocketHandle* handle); | 504 void InvokeUserCallback(ClientSocketHandle* handle); |
503 | 505 |
504 GroupMap group_map_; | 506 GroupMap group_map_; |
505 | 507 |
506 // Map of the ClientSocketHandles for which we have a pending Task to invoke a | 508 // Map of the ClientSocketHandles for which we have a pending Task to invoke a |
(...skipping 27 matching lines...) Expand all Loading... |
534 const scoped_ptr<ConnectJobFactory> connect_job_factory_; | 536 const scoped_ptr<ConnectJobFactory> connect_job_factory_; |
535 | 537 |
536 // TODO(vandebo) Remove when backup jobs move to TCPClientSocketPool | 538 // TODO(vandebo) Remove when backup jobs move to TCPClientSocketPool |
537 bool connect_backup_jobs_enabled_; | 539 bool connect_backup_jobs_enabled_; |
538 | 540 |
539 // A unique id for the pool. It gets incremented every time we Flush() the | 541 // A unique id for the pool. It gets incremented every time we Flush() the |
540 // pool. This is so that when sockets get released back to the pool, we can | 542 // pool. This is so that when sockets get released back to the pool, we can |
541 // make sure that they are discarded rather than reused. | 543 // make sure that they are discarded rather than reused. |
542 int pool_generation_number_; | 544 int pool_generation_number_; |
543 | 545 |
544 ScopedRunnableMethodFactory<ClientSocketPoolBaseHelper> method_factory_; | 546 base::ThunkCanceller thunk_canceller_; |
545 | 547 |
546 DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBaseHelper); | 548 DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBaseHelper); |
547 }; | 549 }; |
548 | 550 |
549 } // namespace internal | 551 } // namespace internal |
550 | 552 |
551 // The maximum duration, in seconds, to keep used idle persistent sockets alive. | 553 // The maximum duration, in seconds, to keep used idle persistent sockets alive. |
552 static const int kUsedIdleSocketTimeout = 300; // 5 minutes | 554 static const int kUsedIdleSocketTimeout = 300; // 5 minutes |
553 | 555 |
554 template <typename SocketParams> | 556 template <typename SocketParams> |
555 class ClientSocketPoolBase { | 557 class ClientSocketPoolBase { |
556 public: | 558 public: |
557 class Request : public internal::ClientSocketPoolBaseHelper::Request { | 559 class Request : public internal::ClientSocketPoolBaseHelper::Request { |
558 public: | 560 public: |
| 561 // Do a hacky type transition from the CompletionCallback to |
| 562 // Tr1CompletionCallback by binding the method. This is complicated |
| 563 // by the fact that the function we're wrapper has overloads which |
| 564 // screws up the type inference. This should not be an issue in most |
| 565 // of the our code since overloads are discouraged by the style guide. |
| 566 // |
| 567 // Also note that we don't need to keep a reference to the callback |
| 568 // because the API does not take ownership. One plus of Tr1 callback is |
| 569 // that there is no such ownership ambiguity. But the downside is |
| 570 // refcounting in the callback. |
| 571 static void RunCallback(CompletionCallback* c, int n) { |
| 572 c->Run(n); |
| 573 } |
| 574 |
559 Request(ClientSocketHandle* handle, | 575 Request(ClientSocketHandle* handle, |
560 CompletionCallback* callback, | 576 CompletionCallback* callback, |
561 RequestPriority priority, | 577 RequestPriority priority, |
562 internal::ClientSocketPoolBaseHelper::Flags flags, | 578 internal::ClientSocketPoolBaseHelper::Flags flags, |
563 const scoped_refptr<SocketParams>& params, | 579 const scoped_refptr<SocketParams>& params, |
564 const BoundNetLog& net_log) | 580 const BoundNetLog& net_log) |
565 : internal::ClientSocketPoolBaseHelper::Request( | 581 : internal::ClientSocketPoolBaseHelper::Request( |
566 handle, callback, priority, flags, net_log), | 582 handle, |
| 583 base::Prebind(&Request::RunCallback, callback), |
| 584 priority, |
| 585 flags, net_log), |
567 params_(params) {} | 586 params_(params) {} |
568 | 587 |
569 const scoped_refptr<SocketParams>& params() const { return params_; } | 588 const scoped_refptr<SocketParams>& params() const { return params_; } |
570 | 589 |
571 private: | 590 private: |
572 const scoped_refptr<SocketParams> params_; | 591 const scoped_refptr<SocketParams> params_; |
573 }; | 592 }; |
574 | 593 |
575 class ConnectJobFactory { | 594 class ConnectJobFactory { |
576 public: | 595 public: |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
736 // Histograms for the pool | 755 // Histograms for the pool |
737 ClientSocketPoolHistograms* const histograms_; | 756 ClientSocketPoolHistograms* const histograms_; |
738 internal::ClientSocketPoolBaseHelper helper_; | 757 internal::ClientSocketPoolBaseHelper helper_; |
739 | 758 |
740 DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBase); | 759 DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBase); |
741 }; | 760 }; |
742 | 761 |
743 } // namespace net | 762 } // namespace net |
744 | 763 |
745 #endif // NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_ | 764 #endif // NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_ |
OLD | NEW |