1// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef NET_BASE_BACKOFF_ITEM_H_
6#define NET_BASE_BACKOFF_ITEM_H_
7#pragma once
8
9#include "base/threading/non_thread_safe.h"
10#include "base/time.h"
11
12namespace net {
13
14// Provides the core logic needed for randomized exponential back-off
15// on requests to a given resource, given a back-off policy.
16//
17// This utility class knows nothing about network specifics; it is
18// intended for reuse in various networking scenarios.
19class BackoffEntry : public base::NonThreadSafe {
20 public:
21  // The set of parameters that define a back-off policy.
22  struct Policy {
23    // Number of initial errors (in sequence) to ignore before applying
24    // exponential back-off rules.
25    int num_errors_to_ignore;
26
27    // Initial delay for exponential back-off.
28    int initial_backoff_ms;
29
30    // Factor by which the waiting time will be multiplied.
31    double multiply_factor;
32
33    // Fuzzing percentage. ex: 10% will spread requests randomly
34    // between 90%-100% of the calculated time.
35    double jitter_factor;
36
37    // Maximum amount of time we are willing to delay our request.
38    int maximum_backoff_ms;
39
40    // Time to keep an entry from being discarded even when it
41    // has no significant state, -1 to never discard.
42    int entry_lifetime_ms;
43  };
44
45  // Lifetime of policy must enclose lifetime of BackoffEntry. The
46  // pointer must be valid but is not dereferenced during construction.
47  explicit BackoffEntry(const Policy* const policy);
48  virtual ~BackoffEntry();
49
50  // Inform this item that a request for the network resource it is
51  // tracking was made, and whether it failed or succeeded.
52  void InformOfRequest(bool succeeded);
53
54  // Returns true if a request for the resource this item tracks should
55  // be rejected at the present time due to exponential back-off policy.
56  bool ShouldRejectRequest() const;
57
58  // Returns the absolute time after which this entry (given its present
59  // state) will no longer reject requests.
60  base::TimeTicks GetReleaseTime() const;
61
62  // Causes this object reject requests until the specified absolute time.
63  // This can be used to e.g. implement support for a Retry-After header.
64  void SetCustomReleaseTime(const base::TimeTicks& release_time);
65
66  // Returns true if this object has no significant state (i.e. you could
67  // just as well start with a fresh BackoffEntry object), and hasn't
68  // had for Policy::entry_lifetime_ms_.
69  bool CanDiscard() const;
70
71 protected:
72  // Equivalent to TimeTicks::Now(), virtual so unit tests can override.
73  // TODO(joi): Switch to constructor-time dependency injection?
74  virtual base::TimeTicks GetTimeNow() const;
75
76 private:
77  // Calculates when requests should again be allowed through.
78  base::TimeTicks CalculateReleaseTime() const;
79
80  // Timestamp calculated by the exponential back-off algorithm at which we are
81  // allowed to start sending requests again.
82  base::TimeTicks exponential_backoff_release_time_;
83
84  // Counts request errors; reset on success.
85  int failure_count_;
86
87  const Policy* const policy_;
88
89  DISALLOW_COPY_AND_ASSIGN(BackoffEntry);
90};
91
92}  // namespace net
93
94#endif  // NET_BASE_BACKOFF_ITEM_H_
95