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
3// found in the LICENSE file.
4
5#ifndef NET_BASE_BACKOFF_ENTRY_H_
6#define NET_BASE_BACKOFF_ENTRY_H_
7
8#include "base/threading/non_thread_safe.h"
9#include "base/time/time.h"
10#include "net/base/net_export.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 NET_EXPORT BackoffEntry : NON_EXPORTED_BASE(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.  The interpretation of this value depends on
28    // always_use_initial_delay.  It's either how long we wait between
29    // requests before backoff starts, or how much we delay the first request
30    // after backoff starts.
31    int initial_delay_ms;
32
33    // Factor by which the waiting time will be multiplied.
34    double multiply_factor;
35
36    // Fuzzing percentage. ex: 10% will spread requests randomly
37    // between 90%-100% of the calculated time.
38    double jitter_factor;
39
40    // Maximum amount of time we are willing to delay our request, -1
41    // for no maximum.
42    int64 maximum_backoff_ms;
43
44    // Time to keep an entry from being discarded even when it
45    // has no significant state, -1 to never discard.
46    int64 entry_lifetime_ms;
47
48    // If true, we always use a delay of initial_delay_ms, even before
49    // we've seen num_errors_to_ignore errors.  Otherwise, initial_delay_ms
50    // is the first delay once we start exponential backoff.
51    //
52    // So if we're ignoring 1 error, we'll see (N, N, Nm, Nm^2, ...) if true,
53    // and (0, 0, N, Nm, ...) when false, where N is initial_backoff_ms and
54    // m is multiply_factor, assuming we've already seen one success.
55    bool always_use_initial_delay;
56  };
57
58  // Lifetime of policy must enclose lifetime of BackoffEntry. The
59  // pointer must be valid but is not dereferenced during construction.
60  explicit BackoffEntry(const Policy* const policy);
61  virtual ~BackoffEntry();
62
63  // Inform this item that a request for the network resource it is
64  // tracking was made, and whether it failed or succeeded.
65  void InformOfRequest(bool succeeded);
66
67  // Returns true if a request for the resource this item tracks should
68  // be rejected at the present time due to exponential back-off policy.
69  bool ShouldRejectRequest() const;
70
71  // Returns the absolute time after which this entry (given its present
72  // state) will no longer reject requests.
73  base::TimeTicks GetReleaseTime() const;
74
75  // Returns the time until a request can be sent.
76  base::TimeDelta GetTimeUntilRelease() const;
77
78  // Causes this object reject requests until the specified absolute time.
79  // This can be used to e.g. implement support for a Retry-After header.
80  void SetCustomReleaseTime(const base::TimeTicks& release_time);
81
82  // Returns true if this object has no significant state (i.e. you could
83  // just as well start with a fresh BackoffEntry object), and hasn't
84  // had for Policy::entry_lifetime_ms.
85  bool CanDiscard() const;
86
87  // Resets this entry to a fresh (as if just constructed) state.
88  void Reset();
89
90  // Returns the failure count for this entry.
91  int failure_count() const { return failure_count_; }
92
93 protected:
94  // Equivalent to TimeTicks::Now(), virtual so unit tests can override.
95  virtual base::TimeTicks ImplGetTimeNow() const;
96
97 private:
98  // Calculates when requests should again be allowed through.
99  base::TimeTicks CalculateReleaseTime() const;
100
101  // Timestamp calculated by the exponential back-off algorithm at which we are
102  // allowed to start sending requests again.
103  base::TimeTicks exponential_backoff_release_time_;
104
105  // Counts request errors; decremented on success.
106  int failure_count_;
107
108  const Policy* const policy_;
109
110  DISALLOW_COPY_AND_ASSIGN(BackoffEntry);
111};
112
113}  // namespace net
114
115#endif  // NET_BASE_BACKOFF_ENTRY_H_
116