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