The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
# -*-perl-*-
use strict;
use warnings;
use Test::More;
use FindBin qw($Bin);
use Time::HiRes qw(sleep);
use MogileFS::Server;
use MogileFS::Test;
find_mogclient_or_skip();
use MogileFS::Admin;
use File::Temp;

my $sto = eval { temp_store(); };
if (!$sto) {
    plan skip_all => "Can't create temporary test database: $@";
    exit 0;
}

my %mogroot;
$mogroot{1} = File::Temp::tempdir( CLEANUP => 1 );
my $dev2host = { 1 => 1, 2 => 1, 3 => 1 };
foreach (sort { $a <=> $b } keys %$dev2host) {
    my $root = $mogroot{$dev2host->{$_}};
    mkdir("$root/dev$_") or die "Failed to create dev$_ dir: $!";
}

my $ms1 = create_mogstored("127.0.1.1", $mogroot{1});
ok($ms1, "got mogstored");

while (! -e "$mogroot{1}/dev1/usage" ||
       ! -e "$mogroot{1}/dev2/usage" ||
       ! -e "$mogroot{1}/dev3/usage") {
    print "Waiting on usage...\n";
    sleep(.25);
}

my $tmptrack = create_temp_tracker($sto);
ok($tmptrack);

my $admin = IO::Socket::INET->new(PeerAddr => '127.0.0.1:7001');
$admin or die "failed to create admin socket: $!";
my $moga = MogileFS::Admin->new(hosts => [ "127.0.0.1:7001" ]);
my $mogc = MogileFS::Client->new(
                                 domain => "testdom",
                                 hosts  => [ "127.0.0.1:7001" ],
                                 );

ok($tmptrack->mogadm("host", "add", "hostA", "--ip=127.0.1.1", "--status=alive"), "created hostA");
ok($tmptrack->mogadm("device", "add", "hostA", 1), "created dev1 on hostA");
ok($tmptrack->mogadm("device", "add", "hostA", 2), "created dev2 on hostA");

ok($tmptrack->mogadm("domain", "add", "testdom"), "created test domain");
ok($tmptrack->mogadm("class", "add", "testdom", "2copies", "--mindevcount=2"), "created 2copies class in testdom");
ok($tmptrack->mogadm("settings", "set", "queue_rate_for_reaper", 123), "set queue_rate_for_reaper");

# create one sample file with 2 copies
my $fh = $mogc->new_file("file1", "2copies");
ok($fh, "got filehandle");
ok(close($fh), "closed file");

my $tries;
my @urls;

# wait for it to replicate
for ($tries = 100; $tries--; ) {
    @urls = $mogc->get_paths("file1");
    last if scalar(@urls) == 2;
    sleep .1;
}

is(scalar(@urls), 2, "replicated to 2 paths");
my $orig_urls = join("\n", sort(@urls));

# add a new device and mark an existing device as dead
ok($tmptrack->mogadm("device", "add", "hostA", 3), "created dev3 on hostA");
ok($tmptrack->mogadm("device", "mark", "hostA", 2, "dead"), "mark dev2 as dead");

# reaper should notice the dead device in 5-10s
for ($tries = 100; $tries--; ) {
    @urls = $mogc->get_paths("file1");
    last if scalar(grep(m{/dev2/}, @urls)) == 0;
    sleep 0.1;
}
is(scalar(grep(m{/dev2/}, @urls)), 0, "file1 no longer references dead dev2");

# replicator should replicate the file within 15-30s
for ($tries = 300; $tries--; ) {
    @urls = sort($mogc->get_paths("file1"));
    last if (scalar(@urls) == 2) && (join("\n", @urls) ne $orig_urls);
    sleep 0.1;
}
is(grep(m{/dev3/}, @urls), 1, "file1 got copied to dev3");
is(scalar(@urls), 2, "we have 2 paths for file1 again");

done_testing();