Skip to content

Commit

Permalink
Checks for requesting timeouts.
Browse files Browse the repository at this point in the history
  • Loading branch information
rakshasa committed Nov 30, 2011
1 parent 19d4842 commit d5be349
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 1 deletion.
40 changes: 40 additions & 0 deletions src/torrent/tracker_controller.cc
Expand Up @@ -336,6 +336,46 @@ TrackerController::stop_requesting() {
update_timeout((*m_tracker_list->find_usable(m_tracker_list->begin()))->normal_interval());
}

uint32_t
tracker_next_timeout(Tracker* tracker, int controller_flags) {
if ((tracker->is_busy() && tracker->latest_event() != Tracker::EVENT_SCRAPE) ||
!tracker->is_usable())
return ~uint32_t();

if ((controller_flags & TrackerController::flag_promiscuous_mode))
return 0;

if ((controller_flags & TrackerController::flag_requesting)) {
std::pair<int, int> timeout_base;

if (tracker->failed_counter())
timeout_base = std::make_pair(5, tracker->failed_counter() - 1);
else if (tracker->latest_sum_peers() < 10)
timeout_base = std::make_pair(10, tracker->success_counter());
else if (tracker->latest_new_peers() < 10)
timeout_base = std::make_pair(30, tracker->success_counter());
else
// We got peers from this tracker, re-request a bit sooner.
timeout_base = std::make_pair(5, tracker->success_counter());

int32_t min_interval = std::min((int)tracker->min_interval(), 600);

int32_t tracker_timeout = std::min(min_interval, (timeout_base.first << std::min(timeout_base.second, 6)));
int32_t since_last = cachedTime.seconds() - (int32_t)tracker->activity_time_last();

return std::max(tracker_timeout - since_last, 0);
}

// if (tracker->success_counter() == 0 && tracker->failed_counter() == 0)
// return 0;

int32_t last_activity = cachedTime.seconds() - tracker->activity_time_last();

// TODO: Use min interval if we're requesting manual update.

return tracker->normal_interval() - std::min(last_activity, (int32_t)tracker->normal_interval());
}

void
TrackerController::do_timeout() {
if (!(m_flags & flag_active) || !m_tracker_list->has_usable())
Expand Down
2 changes: 2 additions & 0 deletions src/torrent/tracker_controller.h
Expand Up @@ -149,6 +149,8 @@ class LIBTORRENT_EXPORT TrackerController {
tracker_controller_private* m_private;
};

uint32_t tracker_next_timeout(Tracker* tracker, int controller_flags);

}

#endif
91 changes: 91 additions & 0 deletions test/torrent/tracker_controller_test.cc
Expand Up @@ -173,6 +173,97 @@ tracker_controller_test::test_timeout() {
TEST_SINGLE_END(0, 0);
}

void
tracker_controller_test::test_timeout_tracker() {
TrackerTest tracker(NULL, "");
int flags = 0;

CPPUNIT_ASSERT(torrent::tracker_next_timeout(&tracker, flags) == 0);
torrent::cachedTime += rak::timer::from_seconds(3);
CPPUNIT_ASSERT(torrent::tracker_next_timeout(&tracker, flags) == 0);

flags = torrent::TrackerController::flag_active;

CPPUNIT_ASSERT(torrent::tracker_next_timeout(&tracker, flags) == 0);
tracker.send_state(torrent::Tracker::EVENT_NONE);
CPPUNIT_ASSERT(torrent::tracker_next_timeout(&tracker, flags) == ~uint32_t());
tracker.send_state(torrent::Tracker::EVENT_SCRAPE);
CPPUNIT_ASSERT(torrent::tracker_next_timeout(&tracker, flags) == 0);

tracker.close();
tracker.set_success(1, torrent::cachedTime.seconds());

// Check also failed...

CPPUNIT_ASSERT(torrent::tracker_next_timeout(&tracker, flags) == 1800);
tracker.send_state(torrent::Tracker::EVENT_NONE);
CPPUNIT_ASSERT(torrent::tracker_next_timeout(&tracker, flags) == ~uint32_t());
tracker.send_state(torrent::Tracker::EVENT_SCRAPE);
CPPUNIT_ASSERT(torrent::tracker_next_timeout(&tracker, flags) == 1800);

tracker.close();

tracker.set_success(1, torrent::cachedTime.seconds() - 3);
CPPUNIT_ASSERT(torrent::tracker_next_timeout(&tracker, flags) == 1800 - 3);
tracker.set_success(1, torrent::cachedTime.seconds() + 3);
CPPUNIT_ASSERT(torrent::tracker_next_timeout(&tracker, flags) == 1800 + 3);

tracker.close();
flags = torrent::TrackerController::flag_active | torrent::TrackerController::flag_promiscuous_mode;

CPPUNIT_ASSERT(torrent::tracker_next_timeout(&tracker, flags) == 0);
tracker.send_state(torrent::Tracker::EVENT_NONE);
CPPUNIT_ASSERT(torrent::tracker_next_timeout(&tracker, flags) == ~uint32_t());
tracker.send_state(torrent::Tracker::EVENT_SCRAPE);
CPPUNIT_ASSERT(torrent::tracker_next_timeout(&tracker, flags) == 0);
}

void
tracker_controller_test::test_timeout_requesting() {
TrackerTest tracker(NULL, "");
int flags = 0;

flags = torrent::TrackerController::flag_active | torrent::TrackerController::flag_requesting;

CPPUNIT_ASSERT(torrent::tracker_next_timeout(&tracker, flags) == 0);
tracker.send_state(torrent::Tracker::EVENT_SCRAPE);
CPPUNIT_ASSERT(torrent::tracker_next_timeout(&tracker, flags) == 0);
tracker.send_state(torrent::Tracker::EVENT_NONE);
CPPUNIT_ASSERT(torrent::tracker_next_timeout(&tracker, flags) == ~uint32_t());

// tracker.set_latest_new_peers(10 - 1);

tracker.close();
tracker.set_failed(1, torrent::cachedTime.seconds());
CPPUNIT_ASSERT(torrent::tracker_next_timeout(&tracker, flags) == 5);
tracker.set_failed(2, torrent::cachedTime.seconds());
CPPUNIT_ASSERT(torrent::tracker_next_timeout(&tracker, flags) == 10);
tracker.set_failed(6 + 1, torrent::cachedTime.seconds());
CPPUNIT_ASSERT(torrent::tracker_next_timeout(&tracker, flags) == 320);
tracker.set_failed(7 + 1, torrent::cachedTime.seconds());
CPPUNIT_ASSERT(torrent::tracker_next_timeout(&tracker, flags) == 320);

//std::cout << "timeout:" << torrent::tracker_next_timeout(&tracker, flags) << std::endl;

tracker.set_failed(0, torrent::cachedTime.seconds());
tracker.set_success(0, torrent::cachedTime.seconds());
CPPUNIT_ASSERT(torrent::tracker_next_timeout(&tracker, flags) == 10);
tracker.set_success(1, torrent::cachedTime.seconds());
CPPUNIT_ASSERT(torrent::tracker_next_timeout(&tracker, flags) == 20);
tracker.set_success(5, torrent::cachedTime.seconds());
CPPUNIT_ASSERT(torrent::tracker_next_timeout(&tracker, flags) == 320);
tracker.set_success(6, torrent::cachedTime.seconds());
CPPUNIT_ASSERT(torrent::tracker_next_timeout(&tracker, flags) == 600);

tracker.set_latest_sum_peers(10);
tracker.set_success(0, torrent::cachedTime.seconds());
CPPUNIT_ASSERT(torrent::tracker_next_timeout(&tracker, flags) == 30);

tracker.set_latest_new_peers(10);
tracker.set_success(0, torrent::cachedTime.seconds());
CPPUNIT_ASSERT(torrent::tracker_next_timeout(&tracker, flags) == 5);
}

void
tracker_controller_test::test_single_success() {
TEST_SINGLE_BEGIN();
Expand Down
4 changes: 4 additions & 0 deletions test/torrent/tracker_controller_test.h
Expand Up @@ -9,6 +9,8 @@ class tracker_controller_test : public CppUnit::TestFixture {
CPPUNIT_TEST(test_enable);
CPPUNIT_TEST(test_requesting);
CPPUNIT_TEST(test_timeout);
CPPUNIT_TEST(test_timeout_tracker);
CPPUNIT_TEST(test_timeout_requesting);

CPPUNIT_TEST(test_single_success);
CPPUNIT_TEST(test_single_failure);
Expand Down Expand Up @@ -50,6 +52,8 @@ class tracker_controller_test : public CppUnit::TestFixture {
void test_disable();
void test_requesting();
void test_timeout();
void test_timeout_tracker();
void test_timeout_requesting();

void test_single_success();
void test_single_failure();
Expand Down
7 changes: 6 additions & 1 deletion test/torrent/tracker_list_test.h
Expand Up @@ -81,11 +81,16 @@ class TrackerTest : public torrent::Tracker {
void set_scrape_on_success(bool state) { if (state) m_flags |= flag_scrape_on_success; else m_flags &= ~flag_scrape_on_success; }
void set_can_scrape() { m_flags |= flag_can_scrape; }

private:
void set_success(uint32_t counter, uint32_t time_last) { m_success_counter = counter; m_success_time_last = time_last; }
void set_failed(uint32_t counter, uint32_t time_last) { m_failed_counter = counter; m_failed_time_last = time_last; }
void set_latest_new_peers(uint32_t peers) { m_latest_new_peers = peers; }
void set_latest_sum_peers(uint32_t peers) { m_latest_sum_peers = peers; }

virtual void send_state(int state) { m_busy = true; m_open = true; m_requesting_state = m_latest_event = state; }
virtual void send_scrape() { m_busy = true; m_open = true; m_requesting_state = m_latest_event = torrent::Tracker::EVENT_SCRAPE; }
virtual void close() { m_busy = false; m_open = false; m_requesting_state = -1; }

private:
bool m_busy;
bool m_open;
int m_requesting_state;
Expand Down

0 comments on commit d5be349

Please sign in to comment.