| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 159 const Request& request, | 159 const Request& request, |
| 160 ConnectJob::Delegate* delegate, | 160 ConnectJob::Delegate* delegate, |
| 161 LoadLog* load_log) const = 0; | 161 LoadLog* load_log) const = 0; |
| 162 | 162 |
| 163 private: | 163 private: |
| 164 DISALLOW_COPY_AND_ASSIGN(ConnectJobFactory); | 164 DISALLOW_COPY_AND_ASSIGN(ConnectJobFactory); |
| 165 }; | 165 }; |
| 166 | 166 |
| 167 ClientSocketPoolBaseHelper(int max_sockets, | 167 ClientSocketPoolBaseHelper(int max_sockets, |
| 168 int max_sockets_per_group, | 168 int max_sockets_per_group, |
| 169 base::TimeDelta unused_idle_socket_timeout, |
| 170 base::TimeDelta used_idle_socket_timeout, |
| 169 ConnectJobFactory* connect_job_factory); | 171 ConnectJobFactory* connect_job_factory); |
| 170 | 172 |
| 171 ~ClientSocketPoolBaseHelper(); | 173 ~ClientSocketPoolBaseHelper(); |
| 172 | 174 |
| 173 // See ClientSocketPool::RequestSocket for documentation on this function. | 175 // See ClientSocketPool::RequestSocket for documentation on this function. |
| 174 // Note that |request| must be heap allocated. If ERR_IO_PENDING is returned, | 176 // Note that |request| must be heap allocated. If ERR_IO_PENDING is returned, |
| 175 // then ClientSocketPoolBaseHelper takes ownership of |request|. | 177 // then ClientSocketPoolBaseHelper takes ownership of |request|. |
| 176 int RequestSocket(const std::string& group_name, const Request* request); | 178 int RequestSocket(const std::string& group_name, const Request* request); |
| 177 | 179 |
| 178 // See ClientSocketPool::CancelRequest for documentation on this function. | 180 // See ClientSocketPool::CancelRequest for documentation on this function. |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 210 // afterward and receive the socket from the job). | 212 // afterward and receive the socket from the job). |
| 211 static void EnableLateBindingOfSockets(bool enabled); | 213 static void EnableLateBindingOfSockets(bool enabled); |
| 212 | 214 |
| 213 // For testing. | 215 // For testing. |
| 214 bool may_have_stalled_group() const { return may_have_stalled_group_; } | 216 bool may_have_stalled_group() const { return may_have_stalled_group_; } |
| 215 | 217 |
| 216 int NumConnectJobsInGroup(const std::string& group_name) const { | 218 int NumConnectJobsInGroup(const std::string& group_name) const { |
| 217 return group_map_.find(group_name)->second.jobs.size(); | 219 return group_map_.find(group_name)->second.jobs.size(); |
| 218 } | 220 } |
| 219 | 221 |
| 222 // Closes all idle sockets if |force| is true. Else, only closes idle |
| 223 // sockets that timed out or can't be reused. Made public for testing. |
| 224 void CleanupIdleSockets(bool force); |
| 225 |
| 220 private: | 226 private: |
| 221 // Entry for a persistent socket which became idle at time |start_time|. | 227 // Entry for a persistent socket which became idle at time |start_time|. |
| 222 struct IdleSocket { | 228 struct IdleSocket { |
| 223 IdleSocket() : socket(NULL), used(false) {} | 229 IdleSocket() : socket(NULL), used(false) {} |
| 224 ClientSocket* socket; | 230 ClientSocket* socket; |
| 225 base::TimeTicks start_time; | 231 base::TimeTicks start_time; |
| 226 bool used; // Indicates whether or not the socket has been used yet. | 232 bool used; // Indicates whether or not the socket has been used yet. |
| 227 | 233 |
| 228 // An idle socket should be removed if it can't be reused, or has been idle | 234 // An idle socket should be removed if it can't be reused, or has been idle |
| 229 // for too long. |now| is the current time value (TimeTicks::Now()). | 235 // for too long. |now| is the current time value (TimeTicks::Now()). |
| 236 // |timeout| is the length of time to wait before timing out an idle socket. |
| 230 // | 237 // |
| 231 // An idle socket can't be reused if it is disconnected or has received | 238 // An idle socket can't be reused if it is disconnected or has received |
| 232 // data unexpectedly (hence no longer idle). The unread data would be | 239 // data unexpectedly (hence no longer idle). The unread data would be |
| 233 // mistaken for the beginning of the next response if we were to reuse the | 240 // mistaken for the beginning of the next response if we were to reuse the |
| 234 // socket for a new request. | 241 // socket for a new request. |
| 235 bool ShouldCleanup(base::TimeTicks now) const; | 242 bool ShouldCleanup(base::TimeTicks now, base::TimeDelta timeout) const; |
| 236 }; | 243 }; |
| 237 | 244 |
| 238 typedef std::deque<const Request*> RequestQueue; | 245 typedef std::deque<const Request*> RequestQueue; |
| 239 typedef std::map<const ClientSocketHandle*, const Request*> RequestMap; | 246 typedef std::map<const ClientSocketHandle*, const Request*> RequestMap; |
| 240 | 247 |
| 241 // A Group is allocated per group_name when there are idle sockets or pending | 248 // A Group is allocated per group_name when there are idle sockets or pending |
| 242 // requests. Otherwise, the Group object is removed from the map. | 249 // requests. Otherwise, the Group object is removed from the map. |
| 243 struct Group { | 250 struct Group { |
| 244 Group() : active_socket_count(0) {} | 251 Group() : active_socket_count(0) {} |
| 245 | 252 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 267 typedef std::map<std::string, Group> GroupMap; | 274 typedef std::map<std::string, Group> GroupMap; |
| 268 | 275 |
| 269 typedef std::map<const ClientSocketHandle*, ConnectJob*> ConnectJobMap; | 276 typedef std::map<const ClientSocketHandle*, ConnectJob*> ConnectJobMap; |
| 270 typedef std::set<const ConnectJob*> ConnectJobSet; | 277 typedef std::set<const ConnectJob*> ConnectJobSet; |
| 271 | 278 |
| 272 static void InsertRequestIntoQueue(const Request* r, | 279 static void InsertRequestIntoQueue(const Request* r, |
| 273 RequestQueue* pending_requests); | 280 RequestQueue* pending_requests); |
| 274 static const Request* RemoveRequestFromQueue(RequestQueue::iterator it, | 281 static const Request* RemoveRequestFromQueue(RequestQueue::iterator it, |
| 275 RequestQueue* pending_requests); | 282 RequestQueue* pending_requests); |
| 276 | 283 |
| 277 // Closes all idle sockets if |force| is true. Else, only closes idle | |
| 278 // sockets that timed out or can't be reused. | |
| 279 void CleanupIdleSockets(bool force); | |
| 280 | |
| 281 // Called when the number of idle sockets changes. | 284 // Called when the number of idle sockets changes. |
| 282 void IncrementIdleCount(); | 285 void IncrementIdleCount(); |
| 283 void DecrementIdleCount(); | 286 void DecrementIdleCount(); |
| 284 | 287 |
| 285 // Called via PostTask by ReleaseSocket. | 288 // Called via PostTask by ReleaseSocket. |
| 286 void DoReleaseSocket(const std::string& group_name, ClientSocket* socket); | 289 void DoReleaseSocket(const std::string& group_name, ClientSocket* socket); |
| 287 | 290 |
| 288 // Scans the group map for groups which have an available socket slot and | 291 // Scans the group map for groups which have an available socket slot and |
| 289 // at least one pending request. Returns number of groups found, and if found | 292 // at least one pending request. Returns number of groups found, and if found |
| 290 // at least one, fills |group| and |group_name| with data of the stalled group | 293 // at least one, fills |group| and |group_name| with data of the stalled group |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 352 | 355 |
| 353 // Number of connected sockets we handed out across all groups. | 356 // Number of connected sockets we handed out across all groups. |
| 354 int handed_out_socket_count_; | 357 int handed_out_socket_count_; |
| 355 | 358 |
| 356 // The maximum total number of sockets. See ReachedMaxSocketsLimit. | 359 // The maximum total number of sockets. See ReachedMaxSocketsLimit. |
| 357 const int max_sockets_; | 360 const int max_sockets_; |
| 358 | 361 |
| 359 // The maximum number of sockets kept per group. | 362 // The maximum number of sockets kept per group. |
| 360 const int max_sockets_per_group_; | 363 const int max_sockets_per_group_; |
| 361 | 364 |
| 365 // The time to wait until closing idle sockets. |
| 366 const base::TimeDelta unused_idle_socket_timeout_; |
| 367 const base::TimeDelta used_idle_socket_timeout_; |
| 368 |
| 362 // Until the maximum number of sockets limit is reached, a group can only | 369 // Until the maximum number of sockets limit is reached, a group can only |
| 363 // have pending requests if it exceeds the "max sockets per group" limit. | 370 // have pending requests if it exceeds the "max sockets per group" limit. |
| 364 // | 371 // |
| 365 // This means when a socket is released, the only pending requests that can | 372 // This means when a socket is released, the only pending requests that can |
| 366 // be started next belong to the same group. | 373 // be started next belong to the same group. |
| 367 // | 374 // |
| 368 // However once the |max_sockets_| limit is reached, this stops being true: | 375 // However once the |max_sockets_| limit is reached, this stops being true: |
| 369 // groups can now have pending requests without having first reached the | 376 // groups can now have pending requests without having first reached the |
| 370 // |max_sockets_per_group_| limit. So choosing the next request involves | 377 // |max_sockets_per_group_| limit. So choosing the next request involves |
| 371 // selecting the highest priority request across *all* groups. | 378 // selecting the highest priority request across *all* groups. |
| 372 // | 379 // |
| 373 // Since reaching the maximum number of sockets is an edge case, we make note | 380 // Since reaching the maximum number of sockets is an edge case, we make note |
| 374 // of when it happens, and thus avoid doing the slower "scan all groups" | 381 // of when it happens, and thus avoid doing the slower "scan all groups" |
| 375 // in the common case. | 382 // in the common case. |
| 376 bool may_have_stalled_group_; | 383 bool may_have_stalled_group_; |
| 377 | 384 |
| 378 const scoped_ptr<ConnectJobFactory> connect_job_factory_; | 385 const scoped_ptr<ConnectJobFactory> connect_job_factory_; |
| 379 | 386 |
| 380 // Controls whether or not we use late binding of sockets. | 387 // Controls whether or not we use late binding of sockets. |
| 381 static bool g_late_binding; | 388 static bool g_late_binding; |
| 382 | 389 |
| 383 }; | 390 }; |
| 384 | 391 |
| 385 } // namespace internal | 392 } // namespace internal |
| 386 | 393 |
| 394 // The maximum duration, in seconds, to keep unused idle persistent sockets |
| 395 // alive. |
| 396 // TODO(willchan): Change this timeout after getting histogram data on how |
| 397 // long it should be. |
| 398 static const int kUnusedIdleSocketTimeout = 10; |
| 399 // The maximum duration, in seconds, to keep used idle persistent sockets alive. |
| 400 static const int kUsedIdleSocketTimeout = 300; // 5 minutes |
| 401 |
| 387 template <typename SocketParams> | 402 template <typename SocketParams> |
| 388 class ClientSocketPoolBase { | 403 class ClientSocketPoolBase { |
| 389 public: | 404 public: |
| 390 class Request : public internal::ClientSocketPoolBaseHelper::Request { | 405 class Request : public internal::ClientSocketPoolBaseHelper::Request { |
| 391 public: | 406 public: |
| 392 Request(ClientSocketHandle* handle, | 407 Request(ClientSocketHandle* handle, |
| 393 CompletionCallback* callback, | 408 CompletionCallback* callback, |
| 394 int priority, | 409 int priority, |
| 395 const SocketParams& params, | 410 const SocketParams& params, |
| 396 LoadLog* load_log) | 411 LoadLog* load_log) |
| (...skipping 15 matching lines...) Expand all Loading... |
| 412 virtual ConnectJob* NewConnectJob( | 427 virtual ConnectJob* NewConnectJob( |
| 413 const std::string& group_name, | 428 const std::string& group_name, |
| 414 const Request& request, | 429 const Request& request, |
| 415 ConnectJob::Delegate* delegate, | 430 ConnectJob::Delegate* delegate, |
| 416 LoadLog* load_log) const = 0; | 431 LoadLog* load_log) const = 0; |
| 417 | 432 |
| 418 private: | 433 private: |
| 419 DISALLOW_COPY_AND_ASSIGN(ConnectJobFactory); | 434 DISALLOW_COPY_AND_ASSIGN(ConnectJobFactory); |
| 420 }; | 435 }; |
| 421 | 436 |
| 437 // |max_sockets| is the maximum number of sockets to be maintained by this |
| 438 // ClientSocketPool. |max_sockets_per_group| specifies the maximum number of |
| 439 // sockets a "group" can have. |unused_idle_socket_timeout| specifies how |
| 440 // long to leave an unused idle socket open before closing it. |
| 441 // |used_idle_socket_timeout| specifies how long to leave a previously used |
| 442 // idle socket open before closing it. |
| 422 ClientSocketPoolBase(int max_sockets, | 443 ClientSocketPoolBase(int max_sockets, |
| 423 int max_sockets_per_group, | 444 int max_sockets_per_group, |
| 445 base::TimeDelta unused_idle_socket_timeout, |
| 446 base::TimeDelta used_idle_socket_timeout, |
| 424 ConnectJobFactory* connect_job_factory) | 447 ConnectJobFactory* connect_job_factory) |
| 425 : helper_(new internal::ClientSocketPoolBaseHelper( | 448 : helper_(new internal::ClientSocketPoolBaseHelper( |
| 426 max_sockets, max_sockets_per_group, | 449 max_sockets, max_sockets_per_group, |
| 450 unused_idle_socket_timeout, used_idle_socket_timeout, |
| 427 new ConnectJobFactoryAdaptor(connect_job_factory))) {} | 451 new ConnectJobFactoryAdaptor(connect_job_factory))) {} |
| 428 | 452 |
| 429 ~ClientSocketPoolBase() {} | 453 ~ClientSocketPoolBase() {} |
| 430 | 454 |
| 431 // These member functions simply forward to ClientSocketPoolBaseHelper. | 455 // These member functions simply forward to ClientSocketPoolBaseHelper. |
| 432 | 456 |
| 433 // RequestSocket bundles up the parameters into a Request and then forwards to | 457 // RequestSocket bundles up the parameters into a Request and then forwards to |
| 434 // ClientSocketPoolBaseHelper::RequestSocket(). Note that the memory | 458 // ClientSocketPoolBaseHelper::RequestSocket(). Note that the memory |
| 435 // ownership is transferred in the asynchronous (ERR_IO_PENDING) case. | 459 // ownership is transferred in the asynchronous (ERR_IO_PENDING) case. |
| 436 int RequestSocket(const std::string& group_name, | 460 int RequestSocket(const std::string& group_name, |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 478 | 502 |
| 479 // For testing. | 503 // For testing. |
| 480 bool may_have_stalled_group() const { | 504 bool may_have_stalled_group() const { |
| 481 return helper_->may_have_stalled_group(); | 505 return helper_->may_have_stalled_group(); |
| 482 } | 506 } |
| 483 | 507 |
| 484 int NumConnectJobsInGroup(const std::string& group_name) const { | 508 int NumConnectJobsInGroup(const std::string& group_name) const { |
| 485 return helper_->NumConnectJobsInGroup(group_name); | 509 return helper_->NumConnectJobsInGroup(group_name); |
| 486 } | 510 } |
| 487 | 511 |
| 512 void CleanupIdleSockets(bool force) { |
| 513 return helper_->CleanupIdleSockets(force); |
| 514 } |
| 515 |
| 488 private: | 516 private: |
| 489 // This adaptor class exists to bridge the | 517 // This adaptor class exists to bridge the |
| 490 // internal::ClientSocketPoolBaseHelper::ConnectJobFactory and | 518 // internal::ClientSocketPoolBaseHelper::ConnectJobFactory and |
| 491 // ClientSocketPoolBase::ConnectJobFactory types, allowing clients to use the | 519 // ClientSocketPoolBase::ConnectJobFactory types, allowing clients to use the |
| 492 // typesafe ClientSocketPoolBase::ConnectJobFactory, rather than having to | 520 // typesafe ClientSocketPoolBase::ConnectJobFactory, rather than having to |
| 493 // static_cast themselves. | 521 // static_cast themselves. |
| 494 class ConnectJobFactoryAdaptor | 522 class ConnectJobFactoryAdaptor |
| 495 : public internal::ClientSocketPoolBaseHelper::ConnectJobFactory { | 523 : public internal::ClientSocketPoolBaseHelper::ConnectJobFactory { |
| 496 public: | 524 public: |
| 497 typedef typename ClientSocketPoolBase<SocketParams>::ConnectJobFactory | 525 typedef typename ClientSocketPoolBase<SocketParams>::ConnectJobFactory |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 529 // decoupled from socket connection jobs. A socket request may initiate a | 557 // decoupled from socket connection jobs. A socket request may initiate a |
| 530 // socket connection job, but there is no guarantee that that socket | 558 // socket connection job, but there is no guarantee that that socket |
| 531 // connection will service the request (for example, a released socket may | 559 // connection will service the request (for example, a released socket may |
| 532 // service the request sooner, or a higher priority request may come in | 560 // service the request sooner, or a higher priority request may come in |
| 533 // afterward and receive the socket from the job). | 561 // afterward and receive the socket from the job). |
| 534 void EnableLateBindingOfSockets(bool enabled); | 562 void EnableLateBindingOfSockets(bool enabled); |
| 535 | 563 |
| 536 } // namespace net | 564 } // namespace net |
| 537 | 565 |
| 538 #endif // NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_ | 566 #endif // NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_ |
| OLD | NEW |