Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Makefile.PL
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ WriteMakefile(
'LWP::Simple' => 0,
fields => 0,
'Test::More' => 0,
'List::Util' => 0,
},
);

18 changes: 16 additions & 2 deletions lib/MogileFS/Backend.pm
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use Socket qw( MSG_NOSIGNAL PF_INET IPPROTO_TCP SOCK_STREAM );
use Errno qw( EINPROGRESS EWOULDBLOCK EISCONN );
use POSIX ();
use MogileFS::Client;
use List::Util qw/ shuffle /;

use fields ('hosts', # arrayref of "$host:$port" of mogilefsd servers
'host_dead', # "$host:$port" -> $time (of last connect failure)
Expand All @@ -18,6 +19,7 @@ use fields ('hosts', # arrayref of "$host:$port" of mogilefsd servers
'pref_ip', # hashref; { ip => preferred ip }
'timeout', # time in seconds to allow sockets to become readable
'last_host_connected', # "ip:port" of last host connected to
'last_host_idx', # array index of the last host we connected to
'hooks', # hash: hookname -> coderef
);

Expand Down Expand Up @@ -59,6 +61,8 @@ sub _init {
$self->{timeout} = $args{timeout} || 3;
}

$self->{hosts} = [ shuffle(@{ $self->{hosts} }) ];

$self->{host_dead} = {};

return $self;
Expand Down Expand Up @@ -220,6 +224,12 @@ sub err {
return $self->{lasterr} ? 1 : 0;
}

sub force_disconnect {
my MogileFS::Backend $self = shift;
undef $self->{sock_cache};
return;
}

################################################################################
# MogileFS::Backend class methods
#
Expand Down Expand Up @@ -310,12 +320,16 @@ sub _get_sock {

my $size = scalar(@{$self->{hosts}});
my $tries = $size > 15 ? 15 : $size;
my $idx = int(rand() * $size);

unless (defined($self->{last_host_idx})) {
$self->{last_host_idx} = int(rand() * $size);
}

my $now = time();
my $sock;
foreach (1..$tries) {
my $host = $self->{hosts}->[$idx++ % $size];
$self->{last_host_idx} = ($self->{last_host_idx}+1) % $size;
my $host = $self->{hosts}->[$self->{last_host_idx}];

# try dead hosts every 5 seconds
next if $self->{host_dead}->{$host} &&
Expand Down
14 changes: 14 additions & 0 deletions lib/MogileFS/Client.pm
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,20 @@ sub errcode {
return $self->{backend}->errcode;
}

=head2 force_disconnect

Forces the client to disconnect from the tracker, causing it to reconnect
when the next request is made. It will reconnect to a different tracker if
possible. A paranoid application may wish to do to this before retrying a
failed command, on the off chance that another tracker may be working better.

=cut

sub force_disconnect {
my MogileFS::Client $self = shift;
return $self->{backend}->force_disconnect();
}

=head2 readonly

$is_readonly = $mogc->readonly
Expand Down
20 changes: 20 additions & 0 deletions t/30-disconnect.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/usr/bin/perl -w

use strict;
use Test::More;
use MogileFS::Client;

my $obj = bless({
backend => bless({
}, 'MogileFS::Backend')
}, 'MogileFS::Client');

isa_ok($obj, 'MogileFS::Client');

$obj->{backend}->{sock_cache} = 'x';
is($obj->{backend}->{sock_cache}, 'x');

$obj->force_disconnect();
is($obj->{backend}->{sock_cache}, undef);

done_testing();