OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chrome/browser/url_fetcher_protect.h" | |
6 | |
7 // URLFetcherProtectEntry ---------------------------------------------------- | |
8 | |
9 using base::TimeDelta; | |
10 using base::TimeTicks; | |
11 | |
12 // Default parameters. Time is in milliseconds. | |
13 // static | |
14 const int URLFetcherProtectEntry::kDefaultSlidingWindowPeriod = 2000; | |
15 | |
16 const int URLFetcherProtectEntry::kDefaultMaxSendThreshold = 20; | |
17 const int URLFetcherProtectEntry::kDefaultMaxRetries = 0; | |
18 | |
19 const int URLFetcherProtectEntry::kDefaultInitialTimeout = 100; | |
20 const double URLFetcherProtectEntry::kDefaultMultiplier = 2.0; | |
21 const int URLFetcherProtectEntry::kDefaultConstantFactor = 100; | |
22 const int URLFetcherProtectEntry::kDefaultMaximumTimeout = 60000; | |
23 | |
24 | |
25 URLFetcherProtectEntry::URLFetcherProtectEntry() | |
26 : sliding_window_period_(kDefaultSlidingWindowPeriod), | |
27 max_send_threshold_(kDefaultMaxSendThreshold), | |
28 max_retries_(kDefaultMaxRetries), | |
29 initial_timeout_(kDefaultInitialTimeout), | |
30 multiplier_(kDefaultMultiplier), | |
31 constant_factor_(kDefaultConstantFactor), | |
32 maximum_timeout_(kDefaultMaximumTimeout) { | |
33 ResetBackoff(); | |
34 } | |
35 | |
36 URLFetcherProtectEntry::URLFetcherProtectEntry(int sliding_window_period, | |
37 int max_send_threshold, | |
38 int max_retries, | |
39 int initial_timeout, | |
40 double multiplier, | |
41 int constant_factor, | |
42 int maximum_timeout) | |
43 : sliding_window_period_(sliding_window_period), | |
44 max_send_threshold_(max_send_threshold), | |
45 max_retries_(max_retries), | |
46 initial_timeout_(initial_timeout), | |
47 multiplier_(multiplier), | |
48 constant_factor_(constant_factor), | |
49 maximum_timeout_(maximum_timeout) { | |
50 ResetBackoff(); | |
51 } | |
52 | |
53 int URLFetcherProtectEntry::UpdateBackoff(EventType event_type) { | |
54 // request may be sent in different threads | |
55 AutoLock lock(lock_); | |
56 | |
57 TimeDelta t; | |
58 switch (event_type) { | |
59 case SEND: | |
60 t = AntiOverload(); | |
61 break; | |
62 case SUCCESS: | |
63 t = ResetBackoff(); | |
64 break; | |
65 case FAILURE: | |
66 t = IncreaseBackoff(); | |
67 break; | |
68 default: | |
69 NOTREACHED(); | |
70 } | |
71 | |
72 int wait = static_cast<int>(t.InMilliseconds()); | |
73 DCHECK(wait >= 0); | |
74 return wait; | |
75 } | |
76 | |
77 TimeDelta URLFetcherProtectEntry::AntiOverload() { | |
78 TimeDelta sw = TimeDelta::FromMilliseconds(sliding_window_period_); | |
79 TimeTicks now = TimeTicks::Now(); | |
80 // Estimate when the next request will be sent. | |
81 release_time_ = now; | |
82 if (send_log_.size() > 0) { | |
83 release_time_ = std::max(release_time_, send_log_.back()); | |
84 } | |
85 // Checks if there are too many send events in recent time. | |
86 if (send_log_.size() >= static_cast<unsigned>(max_send_threshold_)) { | |
87 release_time_ = std::max(release_time_, send_log_.front() + sw); | |
88 } | |
89 // Logs the new send event. | |
90 send_log_.push(release_time_); | |
91 // Drops the out-of-date events in the event list. | |
92 while (!send_log_.empty() && | |
93 (send_log_.front() + sw <= send_log_.back())) { | |
94 send_log_.pop(); | |
95 } | |
96 return release_time_ - now; | |
97 } | |
98 | |
99 TimeDelta URLFetcherProtectEntry::ResetBackoff() { | |
100 timeout_period_ = initial_timeout_; | |
101 release_time_ = TimeTicks::Now(); | |
102 return TimeDelta::FromMilliseconds(0); | |
103 } | |
104 | |
105 TimeDelta URLFetcherProtectEntry::IncreaseBackoff() { | |
106 TimeTicks now = TimeTicks::Now(); | |
107 | |
108 release_time_ = std::max(release_time_, now) + | |
109 TimeDelta::FromMilliseconds(timeout_period_); | |
110 | |
111 // Calculates the new backoff time. | |
112 timeout_period_ = static_cast<int> | |
113 (multiplier_ * timeout_period_ + constant_factor_); | |
114 if (maximum_timeout_ && timeout_period_ > maximum_timeout_) | |
115 timeout_period_ = maximum_timeout_; | |
116 | |
117 return release_time_ - now; | |
118 } | |
119 | |
120 // URLFetcherProtectManager -------------------------------------------------- | |
121 | |
122 // static | |
123 scoped_ptr<URLFetcherProtectManager> URLFetcherProtectManager::protect_manager_; | |
124 Lock URLFetcherProtectManager::lock_; | |
125 | |
126 URLFetcherProtectManager::~URLFetcherProtectManager() { | |
127 // Deletes all entries | |
128 ProtectService::iterator i; | |
129 for (i = services_.begin(); i != services_.end(); ++i) { | |
130 if (i->second) | |
131 delete i->second; | |
132 } | |
133 } | |
134 | |
135 // static | |
136 URLFetcherProtectManager* URLFetcherProtectManager::GetInstance() { | |
137 AutoLock lock(lock_); | |
138 | |
139 if (protect_manager_.get() == NULL) { | |
140 protect_manager_.reset(new URLFetcherProtectManager()); | |
141 } | |
142 return protect_manager_.get(); | |
143 } | |
144 | |
145 URLFetcherProtectEntry* URLFetcherProtectManager::Register(std::string id) { | |
146 AutoLock lock(lock_); | |
147 | |
148 ProtectService::iterator i = services_.find(id); | |
149 | |
150 if (i != services_.end()) { | |
151 // The entry exists. | |
152 return i->second; | |
153 } | |
154 | |
155 // Creates a new entry. | |
156 URLFetcherProtectEntry* entry = new URLFetcherProtectEntry(); | |
157 services_[id] = entry; | |
158 return entry; | |
159 } | |
160 | |
161 URLFetcherProtectEntry* URLFetcherProtectManager::Register( | |
162 std::string id, URLFetcherProtectEntry* entry) { | |
163 AutoLock lock(lock_); | |
164 | |
165 ProtectService::iterator i = services_.find(id); | |
166 if (i != services_.end()) { | |
167 // The entry exists. | |
168 delete i->second; | |
169 } | |
170 | |
171 services_[id] = entry; | |
172 return entry; | |
173 } | |
OLD | NEW |