infrastructure:diskchecker
Différences
Ci-dessous, les différences entre deux révisions de la page.
Prochaine révision | Révision précédente | ||
infrastructure:diskchecker [2018/09/10 11:51] – créée ronan | infrastructure:diskchecker [2019/01/10 15:18] (Version actuelle) – rguyader | ||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
====== Diskchecker.pl ====== | ====== Diskchecker.pl ====== | ||
+ | <code perl> | ||
+ | # | ||
+ | # | ||
+ | # Brad's el-ghetto do-our-storage-stacks-lie? | ||
+ | # | ||
+ | # https:// | ||
- | # | + | sub usage { |
- | # | + | die <<' |
- | # Brad's el-ghetto do-our-storage-stacks-lie? | + | |
- | # | + | |
- | # https:// | + | |
- | + | ||
- | sub usage { | + | |
- | | + | |
Usage: diskchecker.pl -s < | Usage: diskchecker.pl -s < | ||
- | diskchecker.pl -s < | + | diskchecker.pl -s < |
- | diskchecker.pl -l [port] | + | diskchecker.pl -l [port] |
END | END | ||
- | } | + | } |
- | use strict; | + | use strict; |
- | use IO:: | + | use IO:: |
- | use IO:: | + | use IO:: |
- | use Getopt:: | + | use Getopt:: |
- | use Socket qw(IPPROTO_TCP TCP_NODELAY); | + | use Socket qw(IPPROTO_TCP TCP_NODELAY); |
- | my $server; | + | my $server; |
- | my $listen; | + | my $listen; |
- | usage() unless GetOptions(' | + | usage() unless GetOptions(' |
- | | + | ' |
- | usage() unless $server || $listen; | + | usage() unless $server || $listen; |
- | usage() if | + | usage() if |
- | # LISTEN MODE: | + | # LISTEN MODE: |
- | listen_mode($listen) if $listen; | + | listen_mode($listen) if $listen; |
- | # CLIENT MODE: | + | # CLIENT MODE: |
- | my $LEN = 16 * 1024; # 16kB (same as InnoDB page) | + | my $LEN = 16 * 1024; # 16kB (same as InnoDB page) |
- | my $mode = shift; | + | my $mode = shift; |
- | usage() unless $mode =~ / | + | usage() unless $mode =~ / |
- | my $file = shift or usage(); | + | my $file = shift or usage(); |
- | my $size; | + | my $size; |
- | if ($mode eq " | + | if ($mode eq " |
- | | + | $size = shift or usage(); |
- | } | + | } |
- | $server .= ": | + | $server .= ": |
- | my $sock = IO:: | + | my $sock = IO:: |
- | | + | or die " |
- | setsockopt($sock, | + | setsockopt($sock, |
- | create() if $mode eq " | + | create() if $mode eq " |
- | verify() if $mode eq " | + | verify() if $mode eq " |
- | exit 0; | + | exit 0; |
- | sub verify { | + | sub verify { |
- | | + | sendmsg($sock, |
- | | + | my $error_ct = 0; |
- | | + | my %error_ct; |
- | | + | my $size = -s $file; |
- | | + | my $max_pages = int($size / $LEN); |
- | | + | my $percent; |
- | | + | my $last_dump = 0; |
- | | + | my $show_percent = sub { |
printf " verifying: %.02f%%\n", | printf " verifying: %.02f%%\n", | ||
- | | + | }; |
- | | + | open (F, $file) or die " |
- | | + | while (< |
chomp; | chomp; | ||
my ($page, $good, $val, $ago) = split(/\t/, $_); | my ($page, $good, $val, $ago) = split(/\t/, $_); | ||
Ligne 77: | Ligne 77: | ||
my $now = time; | my $now = time; | ||
if ($last_dump != $now) { | if ($last_dump != $now) { | ||
- | | + | $last_dump = $now; |
- | | + | $show_percent-> |
} | } | ||
Ligne 91: | Ligne 91: | ||
unless ($buf eq $tobe) { | unless ($buf eq $tobe) { | ||
- | | + | $error_ct{$ago}++; |
- | | + | $error_ct++; |
- | | + | print " |
} | } | ||
- | | + | } |
- | | + | $show_percent-> |
- | | + | print "Total errors: $error_ct\n"; |
- | | + | if ($error_ct) { |
print " | print " | ||
foreach (sort { $a <=> $b } keys %error_ct) { | foreach (sort { $a <=> $b } keys %error_ct) { | ||
- | | + | printf " |
} | } | ||
- | } | ||
} | } | ||
+ | } | ||
- | sub create { | + | sub create { |
- | | + | open (F, "> |
- | | + | my $ioh = IO:: |
or die; | or die; | ||
- | | + | my $pages = int( ($size * 1024 * 1024) / $LEN ); # 50 MiB of 16k pages (3200 pages) |
- | | + | my %page_hit; |
- | | + | my $pages_hit = 0; |
- | | + | my $uniq_pages_hit = 0; |
- | | + | my $start = time(); |
- | | + | my $last_dump = $start; |
- | | + | while (1) { |
my $rand = int rand 2000000; | my $rand = int rand 2000000; | ||
my $buf = sprintf(" | my $buf = sprintf(" | ||
Ligne 131: | Ligne 131: | ||
sendmsg($sock, | sendmsg($sock, | ||
- | # now wait for acknowledgement | + | # now wait for acknowledgement |
my $ok = readmsg($sock); | my $ok = readmsg($sock); | ||
die " | die " | ||
Ligne 144: | Ligne 144: | ||
$pages_hit++; | $pages_hit++; | ||
unless ($page_hit{$pagenum}++) { | unless ($page_hit{$pagenum}++) { | ||
- | | + | $uniq_pages_hit++; |
} | } | ||
my $now = time; | my $now = time; | ||
if ($now != $last_dump) { | if ($now != $last_dump) { | ||
- | | + | $last_dump = $now; |
- | | + | my $runtime = $now - $start; |
- | | + | printf(" |
- | $runtime, | + | $runtime, |
- | (100 * $uniq_pages_hit / $pages), | + | (100 * $uniq_pages_hit / $pages), |
- | $size, | + | $size, |
- | $pages_hit, | + | $pages_hit, |
- | $pages_hit / $runtime, | + | $pages_hit / $runtime, |
- | ); | + | ); |
} | } | ||
- | |||
- | } | ||
} | } | ||
+ | } | ||
- | sub readmsg { | + | sub readmsg { |
- | | + | my $sock = shift; |
- | | + | my $len; |
- | | + | my $rv = sysread($sock, |
- | | + | return undef unless $rv == 1; |
- | | + | my $msg; |
- | | + | $rv = sysread($sock, |
- | | + | return $msg; |
- | } | + | } |
- | sub sendmsg { | + | sub sendmsg { |
- | | + | my ($sock, $msg) = @_; |
- | | + | my $rv = syswrite($sock, |
- | | + | my $expect = length($msg) + 1; |
- | | + | die " |
- | | + | return 1; |
- | } | + | } |
- | sub listen_mode { | + | sub listen_mode { |
- | | + | my $port = shift; |
- | | + | my $server = IO:: |
- | Listen => 1, | + | Listen => 1, |
- | LocalPort => $port) | + | LocalPort => $port) |
or die " | or die " | ||
- | | + | while (1) { |
print " | print " | ||
my $sock = $server-> | my $sock = $server-> | ||
- | | + | or die " |
setsockopt($sock, | setsockopt($sock, | ||
Ligne 197: | Ligne 196: | ||
process_incoming_conn($sock); | process_incoming_conn($sock); | ||
exit 0; | exit 0; | ||
- | } | ||
} | } | ||
+ | } | ||
- | sub process_incoming_conn { | + | sub process_incoming_conn { |
- | | + | my $sock = shift; |
- | | + | my $peername = getpeername($sock) or |
- | die " | + | die " |
- | | + | my ($port, $iaddr) = sockaddr_in($peername); |
- | | + | my $ip = inet_ntoa($iaddr); |
- | | + | my $file = "/ |
- | | + | die "[$ip] $file is a symlink" |
- | | + | print "[$ip] New connection\n"; |
- | | + | my $lines = 0; |
- | | + | my %state; |
- | | + | my $end; |
- | | + | while (1) { |
if ($lines) { | if ($lines) { | ||
- | | + | last unless wait_for_readability(fileno($sock), |
} | } | ||
my $line = readmsg($sock); | my $line = readmsg($sock); | ||
Ligne 224: | Ligne 223: | ||
if ($line eq " | if ($line eq " | ||
- | | + | print "[$ip] Sending state info from ${ip}' |
- | | + | open (S, " |
- | | + | while (<S>) { |
- | print $sock $_; | + | print $sock $_; |
- | | + | } |
- | | + | close S; |
- | | + | print "[$ip] Done.\n"; |
- | | + | exit 0; |
} | } | ||
Ligne 239: | Ligne 238: | ||
my ($state, $pagenum, $rand) = split(/\t/, $line); | my ($state, $pagenum, $rand) = split(/\t/, $line); | ||
if ($state eq " | if ($state eq " | ||
- | | + | $state{$pagenum} = [ 0, $rand+0, $now ]; |
- | | + | sendmsg($sock, |
} elsif ($state eq " | } elsif ($state eq " | ||
- | | + | $state{$pagenum} = [ 1, $rand+0, $now ]; |
} | } | ||
print "[$ip] $lines writes\n" | print "[$ip] $lines writes\n" | ||
- | | + | } |
- | | + | print "[$ip] Writing state file...\n"; |
- | | + | open (S, "> |
- | | + | foreach (sort { $a <=> $b } keys %state) { |
my $v = $state{$_}; | my $v = $state{$_}; | ||
my $before_end = $end - $v->[2]; | my $before_end = $end - $v->[2]; | ||
print S " | print S " | ||
- | } | ||
- | print "[$ip] Done.\n"; | ||
} | } | ||
+ | print "[$ip] Done.\n"; | ||
+ | } | ||
- | sub wait_for_readability { | + | sub wait_for_readability { |
- | | + | my ($fileno, $timeout) = @_; |
- | | + | return 0 unless $fileno && $timeout; |
- | | + | my $rin; |
- | | + | vec($rin, $fileno, 1) = 1; |
- | | + | my $nfound = select($rin, |
- | | + | return 0 unless defined $nfound; |
- | | + | return $nfound ? 1 : 0; |
- | } | + | } |
+ | </ | ||
infrastructure/diskchecker.1536580296.txt.gz · Dernière modification : 2018/09/10 11:51 de ronan