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