Logo Search packages:      
Sourcecode: chromium-browser version File versions  Download package

url_fetcher_protect.cc

// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/common/net/url_fetcher_protect.h"

#include "base/logging.h"

// URLFetcherProtectEntry ----------------------------------------------------

using base::TimeDelta;
using base::TimeTicks;

// Default parameters.  Time is in milliseconds.
// static
const int URLFetcherProtectEntry::kDefaultSlidingWindowPeriod = 2000;

const int URLFetcherProtectEntry::kDefaultMaxSendThreshold = 20;
const int URLFetcherProtectEntry::kDefaultMaxRetries = 0;

const int URLFetcherProtectEntry::kDefaultInitialTimeout = 100;
const double URLFetcherProtectEntry::kDefaultMultiplier = 2.0;
const int URLFetcherProtectEntry::kDefaultConstantFactor = 100;
const int URLFetcherProtectEntry::kDefaultMaximumTimeout = 60000;


URLFetcherProtectEntry::URLFetcherProtectEntry()
    : sliding_window_period_(kDefaultSlidingWindowPeriod),
      max_send_threshold_(kDefaultMaxSendThreshold),
      max_retries_(kDefaultMaxRetries),
      initial_timeout_(kDefaultInitialTimeout),
      multiplier_(kDefaultMultiplier),
      constant_factor_(kDefaultConstantFactor),
      maximum_timeout_(kDefaultMaximumTimeout) {
  ResetBackoff();
}

URLFetcherProtectEntry::URLFetcherProtectEntry(int sliding_window_period,
                                               int max_send_threshold,
                                               int max_retries,
                                               int initial_timeout,
                                               double multiplier,
                                               int constant_factor,
                                               int maximum_timeout)
    : sliding_window_period_(sliding_window_period),
      max_send_threshold_(max_send_threshold),
      max_retries_(max_retries),
      initial_timeout_(initial_timeout),
      multiplier_(multiplier),
      constant_factor_(constant_factor),
      maximum_timeout_(maximum_timeout) {
  ResetBackoff();
}

int64 URLFetcherProtectEntry::UpdateBackoff(EventType event_type) {
  // request may be sent in different threads
  AutoLock lock(lock_);

  TimeDelta t;
  switch (event_type) {
    case SEND:
      t = AntiOverload();
      break;
    case SUCCESS:
      t = ResetBackoff();
      break;
    case FAILURE:
      t = IncreaseBackoff();
      break;
    default:
      NOTREACHED();
  }

  int64 wait = t.InMilliseconds();
  DCHECK(wait >= 0);
  return wait;
}

TimeDelta URLFetcherProtectEntry::AntiOverload() {
  TimeDelta sw = TimeDelta::FromMilliseconds(sliding_window_period_);
  TimeTicks now = TimeTicks::Now();
  // Estimate when the next request will be sent.
  release_time_ = now;
  if (send_log_.size() > 0) {
    release_time_ = std::max(release_time_, send_log_.back());
  }
  // Checks if there are too many send events in recent time.
  if (send_log_.size() >= static_cast<unsigned>(max_send_threshold_)) {
    release_time_ = std::max(release_time_, send_log_.front() + sw);
  }
  // Logs the new send event.
  send_log_.push(release_time_);
  // Drops the out-of-date events in the event list.
  while (!send_log_.empty() &&
         (send_log_.front() + sw <= send_log_.back())) {
    send_log_.pop();
  }
  return release_time_ - now;
}

TimeDelta URLFetcherProtectEntry::ResetBackoff() {
  timeout_period_ = initial_timeout_;
  release_time_ = TimeTicks::Now();
  return TimeDelta::FromMilliseconds(0);
}

TimeDelta URLFetcherProtectEntry::IncreaseBackoff() {
  TimeTicks now = TimeTicks::Now();

  release_time_ = std::max(release_time_, now) +
                  TimeDelta::FromMilliseconds(timeout_period_);

  // Calculates the new backoff time.
  timeout_period_ = static_cast<int>
      (multiplier_ * timeout_period_ + constant_factor_);
  if (maximum_timeout_ && timeout_period_ > maximum_timeout_)
    timeout_period_ = maximum_timeout_;

  return release_time_ - now;
}

// URLFetcherProtectManager --------------------------------------------------

// static
scoped_ptr<URLFetcherProtectManager> URLFetcherProtectManager::protect_manager_;
Lock URLFetcherProtectManager::lock_;

URLFetcherProtectManager::~URLFetcherProtectManager() {
  // Deletes all entries
  ProtectService::iterator i;
  for (i = services_.begin(); i != services_.end(); ++i) {
    if (i->second)
      delete i->second;
  }
}

// static
URLFetcherProtectManager* URLFetcherProtectManager::GetInstance() {
  AutoLock lock(lock_);

  if (protect_manager_.get() == NULL) {
    protect_manager_.reset(new URLFetcherProtectManager());
  }
  return protect_manager_.get();
}

URLFetcherProtectEntry* URLFetcherProtectManager::Register(
    const std::string& id) {
  AutoLock lock(lock_);

  ProtectService::iterator i = services_.find(id);

  if (i != services_.end()) {
    // The entry exists.
    return i->second;
  }

  // Creates a new entry.
  URLFetcherProtectEntry* entry = new URLFetcherProtectEntry();
  services_[id] = entry;
  return entry;
}

URLFetcherProtectEntry* URLFetcherProtectManager::Register(
    const std::string& id, URLFetcherProtectEntry* entry) {
  AutoLock lock(lock_);

  ProtectService::iterator i = services_.find(id);
  if (i != services_.end()) {
    // The entry exists.
    delete i->second;
  }

  services_[id] = entry;
  return entry;
}

Generated by  Doxygen 1.6.0   Back to index