From 32373fd7c92fb69896a196dec01a5791968104ed Mon Sep 17 00:00:00 2001 From: Ben Date: Thu, 4 Mar 2010 19:31:29 +0000 Subject: [PATCH] Limit the number of simultaneous connect attempts passed to libpurple. Hopefully this will make the network hammering that contributes to the infamous "conflict" error less likely. --- perl/lib/Thrasher/Component.pm | 7 +++++++ perl/lib/Thrasher/ConnectionManager.pm | 38 +++++++++++++++++++++++++++++++++- 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/perl/lib/Thrasher/Component.pm b/perl/lib/Thrasher/Component.pm index ef11a94..1e585bf 100644 --- a/perl/lib/Thrasher/Component.pm +++ b/perl/lib/Thrasher/Component.pm @@ -970,6 +970,9 @@ sub login { }; } } + if ($USE_CONNECTION_MANAGER) { + Thrasher::ConnectionManager::connection_failure(); + } return; } @@ -987,6 +990,10 @@ sub login { $self->{component_name}) { $self->echo_presence($session, $original_presence_tag); } + + if ($USE_CONNECTION_MANAGER) { + Thrasher::ConnectionManager::connection_success(); + } }; if (!defined($registration_info)) { diff --git a/perl/lib/Thrasher/ConnectionManager.pm b/perl/lib/Thrasher/ConnectionManager.pm index 25afc7a..e31ef80 100644 --- a/perl/lib/Thrasher/ConnectionManager.pm +++ b/perl/lib/Thrasher/ConnectionManager.pm @@ -68,6 +68,17 @@ our %EXPORT_TAGS = (all => \@EXPORT_OK); use Thrasher::Log qw(log debug); require Thrasher::Component; +# $SIMULTANEOUS_CONNECT_BOUND's initial value sets the maximum number +# of simultaneous, possibly asynchronous, connection attempts. It will +# be decremented each time a connection attempt starts and incremented +# when it finishes. Thus, at any given time while the +# ConnectionManager is managing it will be the current number of new +# connect attempts that could start at that time. +# +# This should usually be a low limit. Most protocols have several DNS +# lookups and TCP connections per IM login. +our $SIMULTANEOUS_CONNECT_BOUND = 2; + sub decayable { return new Thrasher::ConnectionManager::Decayable(@_); } @@ -192,7 +203,13 @@ sub request_connect { return 0; } - if (!@queue) { + if ($SIMULTANEOUS_CONNECT_BOUND <= 0) { + log('Enough connect attempts in progress; delaying.'); + push(@queue, $connection_closure); + schedule_connection_executor(1); + return 0; + } + elsif (!@queue) { my ($delay, $forcibly_enqueue) = @{schedule_request()}; # Catch this in the next scheduling run. @@ -235,6 +252,11 @@ sub schedule_connection_executor { my $execution_runner = sub { log(scalar(@queue) . ' connection attempts queued.'); + if (@queue && $SIMULTANEOUS_CONNECT_BOUND <= 0) { + debug('Enough connect attempts in progress (not rescheduled).'); + return 1; + } + my $new_timeout = eval { return connection_executor(); }; @@ -279,6 +301,11 @@ sub connection_executor { return 0; } + elsif ($SIMULTANEOUS_CONNECT_BOUND <= 0) { + # Delay repeat until some connection attempts finish. + return 1; + } + # Otherwise, it's time to take one thing off the queue and run it. my $current_closure = shift @queue; service_request($current_closure); @@ -312,13 +339,22 @@ sub service_request { if ($@) { log("Failure in connection callback: $@"); } + else { + $SIMULTANEOUS_CONNECT_BOUND--; + } } sub connection_success { + $SIMULTANEOUS_CONNECT_BOUND++; + + debug('Connection success managed.'); $success->add(1); } sub connection_failure { + $SIMULTANEOUS_CONNECT_BOUND++; + + debug('Connection failure managed.'); my $current_schedule = schedule_request; if ($current_schedule->[0] != 30) { $failure->add(10); -- 2.11.4.GIT