Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(333)

Side by Side Diff: net/socket/client_socket_pool_base.h

Issue 3198009: Revert 57100 - Only create the backup ConnectJob when it is needed.... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 10 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | net/socket/client_socket_pool_base.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 210 matching lines...) Expand 10 before | Expand all | Expand 10 after
221 return ClientSocketPool::kMaxConnectRetryIntervalMs; 221 return ClientSocketPool::kMaxConnectRetryIntervalMs;
222 } 222 }
223 223
224 // ConnectJob::Delegate methods: 224 // ConnectJob::Delegate methods:
225 virtual void OnConnectJobComplete(int result, ConnectJob* job); 225 virtual void OnConnectJobComplete(int result, ConnectJob* job);
226 226
227 // NetworkChangeNotifier::Observer methods: 227 // NetworkChangeNotifier::Observer methods:
228 virtual void OnIPAddressChanged(); 228 virtual void OnIPAddressChanged();
229 229
230 int NumConnectJobsInGroup(const std::string& group_name) const { 230 int NumConnectJobsInGroup(const std::string& group_name) const {
231 return group_map_.find(group_name)->second->jobs().size(); 231 return group_map_.find(group_name)->second.jobs.size();
232 } 232 }
233 233
234 // Closes all idle sockets if |force| is true. Else, only closes idle 234 // Closes all idle sockets if |force| is true. Else, only closes idle
235 // sockets that timed out or can't be reused. Made public for testing. 235 // sockets that timed out or can't be reused. Made public for testing.
236 void CleanupIdleSockets(bool force); 236 void CleanupIdleSockets(bool force);
237 237
238 base::TimeDelta ConnectionTimeout() const { 238 base::TimeDelta ConnectionTimeout() const {
239 return connect_job_factory_->ConnectionTimeout(); 239 return connect_job_factory_->ConnectionTimeout();
240 } 240 }
241 241
(...skipping 19 matching lines...) Expand all
261 // socket for a new request. 261 // socket for a new request.
262 bool ShouldCleanup(base::TimeTicks now, base::TimeDelta timeout) const; 262 bool ShouldCleanup(base::TimeTicks now, base::TimeDelta timeout) const;
263 }; 263 };
264 264
265 typedef std::deque<const Request*> RequestQueue; 265 typedef std::deque<const Request*> RequestQueue;
266 typedef std::map<const ClientSocketHandle*, const Request*> RequestMap; 266 typedef std::map<const ClientSocketHandle*, const Request*> RequestMap;
267 267
268 // A Group is allocated per group_name when there are idle sockets or pending 268 // A Group is allocated per group_name when there are idle sockets or pending
269 // requests. Otherwise, the Group object is removed from the map. 269 // requests. Otherwise, the Group object is removed from the map.
270 // |active_socket_count| tracks the number of sockets held by clients. 270 // |active_socket_count| tracks the number of sockets held by clients.
271 class Group { 271 struct Group {
272 public: 272 Group()
273 Group(); 273 : active_socket_count(0),
274 ~Group(); 274 backup_job(NULL),
275 backup_task(NULL) {
276 }
277
278 ~Group() {
279 CleanupBackupJob();
280 }
275 281
276 bool IsEmpty() const { 282 bool IsEmpty() const {
277 return active_socket_count_ == 0 && idle_sockets_.empty() && 283 return active_socket_count == 0 && idle_sockets.empty() && jobs.empty() &&
278 jobs_.empty() && pending_requests_.empty(); 284 pending_requests.empty();
279 } 285 }
280 286
281 bool HasAvailableSocketSlot(int max_sockets_per_group) const { 287 bool HasAvailableSocketSlot(int max_sockets_per_group) const {
282 return active_socket_count_ + static_cast<int>(jobs_.size()) < 288 return active_socket_count + static_cast<int>(jobs.size()) <
283 max_sockets_per_group; 289 max_sockets_per_group;
284 } 290 }
285 291
286 bool IsStalled(int max_sockets_per_group) const { 292 bool IsStalled(int max_sockets_per_group) const {
287 return HasAvailableSocketSlot(max_sockets_per_group) && 293 return HasAvailableSocketSlot(max_sockets_per_group) &&
288 pending_requests_.size() > jobs_.size(); 294 pending_requests.size() > jobs.size();
289 } 295 }
290 296
291 RequestPriority TopPendingPriority() const { 297 RequestPriority TopPendingPriority() const {
292 return pending_requests_.front()->priority(); 298 return pending_requests.front()->priority();
293 } 299 }
294 300
295 bool HasBackupJob() const { return !method_factory_.empty(); }
296
297 void CleanupBackupJob() { 301 void CleanupBackupJob() {
298 method_factory_.RevokeAll(); 302 if (backup_job) {
303 delete backup_job;
304 backup_job = NULL;
305 }
306 if (backup_task) {
307 backup_task->Cancel();
308 backup_task = NULL;
309 }
299 } 310 }
300 311
301 // Set a timer to create a backup socket if it takes too long to create one. 312 std::deque<IdleSocket> idle_sockets;
302 void StartBackupSocketTimer(const std::string& group_name, 313 std::set<const ConnectJob*> jobs;
303 ClientSocketPoolBaseHelper* pool); 314 RequestQueue pending_requests;
304 315 int active_socket_count; // number of active sockets used by clients
305 // Called when the backup socket timer fires. 316 // A backup job in case the connect for this group takes too long.
306 void OnBackupSocketTimerFired( 317 ConnectJob* backup_job;
307 std::string group_name, 318 CancelableTask* backup_task;
308 ClientSocketPoolBaseHelper* pool);
309
310 void AddJob(const ConnectJob* job) { jobs_.insert(job); }
311 void RemoveJob(const ConnectJob* job) { jobs_.erase(job); }
312 void RemoveAllJobs();
313
314 void IncrementActiveSocketCount() { active_socket_count_++; }
315 void DecrementActiveSocketCount() { active_socket_count_--; }
316
317 const std::set<const ConnectJob*>& jobs() const { return jobs_; }
318 const std::deque<IdleSocket>& idle_sockets() const { return idle_sockets_; }
319 const RequestQueue& pending_requests() const { return pending_requests_; }
320 int active_socket_count() const { return active_socket_count_; }
321 RequestQueue* mutable_pending_requests() { return &pending_requests_; }
322 std::deque<IdleSocket>* mutable_idle_sockets() { return &idle_sockets_; }
323
324 private:
325 std::deque<IdleSocket> idle_sockets_;
326 std::set<const ConnectJob*> jobs_;
327 RequestQueue pending_requests_;
328 int active_socket_count_; // number of active sockets used by clients
329 // A factory to pin the backup_job tasks.
330 ScopedRunnableMethodFactory<Group> method_factory_;
331 }; 319 };
332 320
333 typedef std::map<std::string, Group*> GroupMap; 321 typedef std::map<std::string, Group> GroupMap;
334 322
335 typedef std::set<const ConnectJob*> ConnectJobSet; 323 typedef std::set<const ConnectJob*> ConnectJobSet;
336 324
337 struct CallbackResultPair { 325 struct CallbackResultPair {
338 CallbackResultPair() : callback(NULL), result(OK) {} 326 CallbackResultPair() : callback(NULL), result(OK) {}
339 CallbackResultPair(CompletionCallback* callback_in, int result_in) 327 CallbackResultPair(CompletionCallback* callback_in, int result_in)
340 : callback(callback_in), result(result_in) {} 328 : callback(callback_in), result(result_in) {}
341 329
342 CompletionCallback* callback; 330 CompletionCallback* callback;
343 int result; 331 int result;
344 }; 332 };
345 333
346 typedef std::map<const ClientSocketHandle*, CallbackResultPair> 334 typedef std::map<const ClientSocketHandle*, CallbackResultPair>
347 PendingCallbackMap; 335 PendingCallbackMap;
348 336
349 ~ClientSocketPoolBaseHelper(); 337 ~ClientSocketPoolBaseHelper();
350 338
351 static void InsertRequestIntoQueue(const Request* r, 339 static void InsertRequestIntoQueue(const Request* r,
352 RequestQueue* pending_requests); 340 RequestQueue* pending_requests);
353 static const Request* RemoveRequestFromQueue(RequestQueue::iterator it, 341 static const Request* RemoveRequestFromQueue(RequestQueue::iterator it,
354 RequestQueue* pending_requests); 342 RequestQueue* pending_requests);
355 343
356 Group* GetOrCreateGroup(const std::string& group_name);
357 void RemoveGroup(const std::string& group_name);
358 void RemoveGroup(GroupMap::iterator it);
359
360 // Called when the number of idle sockets changes. 344 // Called when the number of idle sockets changes.
361 void IncrementIdleCount(); 345 void IncrementIdleCount();
362 void DecrementIdleCount(); 346 void DecrementIdleCount();
363 347
364 // Scans the group map for groups which have an available socket slot and 348 // Scans the group map for groups which have an available socket slot and
365 // at least one pending request. Returns true if any groups are stalled, and 349 // at least one pending request. Returns true if any groups are stalled, and
366 // if so, fills |group| and |group_name| with data of the stalled group 350 // if so, fills |group| and |group_name| with data of the stalled group
367 // having highest priority. 351 // having highest priority.
368 bool FindTopStalledGroup(Group** group, std::string* group_name); 352 bool FindTopStalledGroup(Group** group, std::string* group_name);
369 353
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
403 bool ReachedMaxSocketsLimit() const; 387 bool ReachedMaxSocketsLimit() const;
404 388
405 // This is the internal implementation of RequestSocket(). It differs in that 389 // This is the internal implementation of RequestSocket(). It differs in that
406 // it does not handle logging into NetLog of the queueing status of 390 // it does not handle logging into NetLog of the queueing status of
407 // |request|. 391 // |request|.
408 int RequestSocketInternal(const std::string& group_name, 392 int RequestSocketInternal(const std::string& group_name,
409 const Request* request); 393 const Request* request);
410 394
411 // Assigns an idle socket for the group to the request. 395 // Assigns an idle socket for the group to the request.
412 // Returns |true| if an idle socket is available, false otherwise. 396 // Returns |true| if an idle socket is available, false otherwise.
413 bool AssignIdleSocketToGroup(const Request* request, Group* group); 397 bool AssignIdleSocketToGroup(Group* group, const Request* request);
414 398
415 static void LogBoundConnectJobToRequest( 399 static void LogBoundConnectJobToRequest(
416 const NetLog::Source& connect_job_source, const Request* request); 400 const NetLog::Source& connect_job_source, const Request* request);
417 401
402 // Set a timer to create a backup socket if it takes too long to create one.
403 void StartBackupSocketTimer(const std::string& group_name);
404
405 // Called when the backup socket timer fires.
406 void OnBackupSocketTimerFired(const std::string& group_name);
407
418 // Closes one idle socket. Picks the first one encountered. 408 // Closes one idle socket. Picks the first one encountered.
419 // TODO(willchan): Consider a better algorithm for doing this. Perhaps we 409 // TODO(willchan): Consider a better algorithm for doing this. Perhaps we
420 // should keep an ordered list of idle sockets, and close them in order. 410 // should keep an ordered list of idle sockets, and close them in order.
421 // Requires maintaining more state. It's not clear if it's worth it since 411 // Requires maintaining more state. It's not clear if it's worth it since
422 // I'm not sure if we hit this situation often. 412 // I'm not sure if we hit this situation often.
423 void CloseOneIdleSocket(); 413 void CloseOneIdleSocket();
424 414
425 // Checks if there are stalled socket groups that should be notified 415 // Checks if there are stalled socket groups that should be notified
426 // for possible wakeup. 416 // for possible wakeup.
427 void CheckForStalledSocketGroups(); 417 void CheckForStalledSocketGroups();
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
466 456
467 // The time to wait until closing idle sockets. 457 // The time to wait until closing idle sockets.
468 const base::TimeDelta unused_idle_socket_timeout_; 458 const base::TimeDelta unused_idle_socket_timeout_;
469 const base::TimeDelta used_idle_socket_timeout_; 459 const base::TimeDelta used_idle_socket_timeout_;
470 460
471 const scoped_ptr<ConnectJobFactory> connect_job_factory_; 461 const scoped_ptr<ConnectJobFactory> connect_job_factory_;
472 462
473 // TODO(vandebo) Remove when backup jobs move to TCPClientSocketPool 463 // TODO(vandebo) Remove when backup jobs move to TCPClientSocketPool
474 bool backup_jobs_enabled_; 464 bool backup_jobs_enabled_;
475 465
466 // A factory to pin the backup_job tasks.
467 ScopedRunnableMethodFactory<ClientSocketPoolBaseHelper> method_factory_;
468
476 // A unique id for the pool. It gets incremented every time we Flush() the 469 // A unique id for the pool. It gets incremented every time we Flush() the
477 // pool. This is so that when sockets get released back to the pool, we can 470 // pool. This is so that when sockets get released back to the pool, we can
478 // make sure that they are discarded rather than reused. 471 // make sure that they are discarded rather than reused.
479 int pool_generation_number_; 472 int pool_generation_number_;
480 473
481 // Some parts of this class need to know if the destructor is running. 474 // Some parts of this class need to know if the destructor is running.
482 bool in_destructor_; 475 bool in_destructor_;
483 }; 476 };
484 477
485 } // namespace internal 478 } // namespace internal
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
646 // ClientSocketPoolBase<T> reference to drop to zero. While we're deep 639 // ClientSocketPoolBase<T> reference to drop to zero. While we're deep
647 // in cleanup code, we'll often hold a reference to |self|. 640 // in cleanup code, we'll often hold a reference to |self|.
648 scoped_refptr<internal::ClientSocketPoolBaseHelper> helper_; 641 scoped_refptr<internal::ClientSocketPoolBaseHelper> helper_;
649 642
650 DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBase); 643 DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBase);
651 }; 644 };
652 645
653 } // namespace net 646 } // namespace net
654 647
655 #endif // NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_ 648 #endif // NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_
OLDNEW
« no previous file with comments | « no previous file | net/socket/client_socket_pool_base.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698