Outils pour utilisateurs

Outils du site


infrastructure:diskchecker

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Prochaine révision
Révision précédente
infrastructure:diskchecker [2018/09/10 11:51] – créée ronaninfrastructure:diskchecker [2019/01/10 15:18] (Version actuelle) rguyader
Ligne 1: Ligne 1:
 ====== Diskchecker.pl ====== ====== Diskchecker.pl ======
 +<code perl>
 +#!/usr/bin/perl
 +#
 +# Brad's el-ghetto do-our-storage-stacks-lie?-script
 +#
 +# https://gist.github.com/bradfitz/3172656#file-diskchecker-pl
  
- #!/usr/bin/perl +sub usage { 
-+ die <<'END';
- # Brad's el-ghetto do-our-storage-stacks-lie?-script +
-+
- # https://gist.github.com/bradfitz/3172656#file-diskchecker-pl +
- +
- sub usage { +
-     die <<'END';+
  Usage: diskchecker.pl -s <server[:port]> verify <file>  Usage: diskchecker.pl -s <server[:port]> verify <file>
-        diskchecker.pl -s <server[:port]> create <file> <size_in_MB> + diskchecker.pl -s <server[:port]> create <file> <size_in_MB> 
-        diskchecker.pl -l [port]+ diskchecker.pl -l [port]
  END  END
- }+}
  
- use strict; +use strict; 
- use IO::Socket::INET; +use IO::Socket::INET; 
- use IO::Handle; +use IO::Handle; 
- use Getopt::Long; +use Getopt::Long; 
- 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('server=s' => \$server, +usage() unless GetOptions('server=s' => \$server, 
-   'listen:5400' => \$listen); + 'listen:5400' => \$listen); 
- usage() unless $server || $listen; +usage() unless $server || $listen; 
- usage() if     $server && $listen;+usage() if     $server && $listen;
  
- # 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 =~ /^verify|create$/;+usage() unless $mode =~ /^verify|create$/;
  
- my $file = shift or usage(); +my $file = shift or usage(); 
- my $size; +my $size; 
- if ($mode eq "create") { +if ($mode eq "create") { 
-     $size = shift or usage(); + $size = shift or usage(); 
- }+}
  
- $server .= ":5400" unless $server =~ /:/;+$server .= ":5400" unless $server =~ /:/;
  
- my $sock = IO::Socket::INET->new(PeerAddr => $server) +my $sock = IO::Socket::INET->new(PeerAddr => $server) 
-     or die "Couldn't connect to host:port of '$server'\n";+ or die "Couldn't connect to host:port of '$server'\n";
  
- setsockopt($sock, IPPROTO_TCP, TCP_NODELAY, pack("l", 1)) or die;+setsockopt($sock, IPPROTO_TCP, TCP_NODELAY, pack("l", 1)) or die;
  
- create() if $mode eq "create"; +create() if $mode eq "create"; 
- verify() if $mode eq "verify"; +verify() if $mode eq "verify"; 
- exit 0;+exit 0;
  
- sub verify { +sub verify { 
-     sendmsg($sock, "read");+ sendmsg($sock, "read");
  
-     my $error_ct = 0; + my $error_ct = 0; 
-     my %error_ct;+ my %error_ct;
  
-     my $size = -s $file; + my $size = -s $file; 
-     my $max_pages = int($size / $LEN);+ my $max_pages = int($size / $LEN);
  
-     my $percent; + my $percent; 
-     my $last_dump = 0; + my $last_dump = 0; 
-     my $show_percent = sub {+ my $show_percent = sub {
  printf " verifying: %.02f%%\n", $percent;  printf " verifying: %.02f%%\n", $percent;
-     };+ };
  
-     open (F, $file) or die "Couldn't open file $file for read\n";+ open (F, $file) or die "Couldn't open file $file for read\n";
  
-     while (<$sock>) {+ while (<$sock>) {
  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; + $last_dump = $now; 
-     $show_percent->();+ $show_percent->();
  }  }
  
Ligne 91: Ligne 91:
  
  unless ($buf eq $tobe) {  unless ($buf eq $tobe) {
-     $error_ct{$ago}++; + $error_ct{$ago}++; 
-     $error_ct++; + $error_ct++; 
-     print "  Error at page $page, $ago seconds before end.\n";+ print "  Error at page $page, $ago seconds before end.\n";
  }  }
-     +
-     $show_percent->();+ $show_percent->();
  
-     print "Total errors: $error_ct\n"; + print "Total errors: $error_ct\n"; 
-     if ($error_ct) {+ if ($error_ct) {
  print "Histogram of seconds before end:\n";  print "Histogram of seconds before end:\n";
  foreach (sort { $a <=> $b } keys %error_ct) {  foreach (sort { $a <=> $b } keys %error_ct) {
-     printf "  %4d %4d\n", $_, $error_ct{$_};+ printf "  %4d %4d\n", $_, $error_ct{$_};
  }  }
-     } 
  }  }
 +}
  
- sub create { +sub create { 
-     open (F, ">$file") or die "Couldn't open file $file\n";+ open (F, ">$file") or die "Couldn't open file $file\n";
  
-     my $ioh = IO::Handle->new_from_fd(fileno(F), "w")+ my $ioh = IO::Handle->new_from_fd(fileno(F), "w")
  or die;  or die;
  
-     my $pages = int( ($size * 1024 * 1024) / $LEN );  # 50 MiB of 16k pages (3200 pages)+ my $pages = int( ($size * 1024 * 1024) / $LEN );  # 50 MiB of 16k pages (3200 pages)
  
-     my %page_hit; + my %page_hit; 
-     my $pages_hit = 0; + my $pages_hit = 0; 
-     my $uniq_pages_hit = 0; + my $uniq_pages_hit = 0; 
-     my $start = time(); + my $start = time(); 
-     my $last_dump = $start;+ my $last_dump = $start;
  
-     while (1) {+ while (1) {
  my $rand = int rand 2000000;  my $rand = int rand 2000000;
  my $buf = sprintf("%08x", $rand) x ($LEN / 8);  my $buf = sprintf("%08x", $rand) x ($LEN / 8);
Ligne 131: Ligne 131:
  sendmsg($sock, "pre\t$pagenum\t$rand");  sendmsg($sock, "pre\t$pagenum\t$rand");
  
- # now wait for acknowledgement+# now wait for acknowledgement
  my $ok = readmsg($sock);  my $ok = readmsg($sock);
  die "didn't get 'ok' from server ($pagenum $rand), msg=[$ok] = $!" unless $ok eq "ok";  die "didn't get 'ok' from server ($pagenum $rand), msg=[$ok] = $!" unless $ok eq "ok";
Ligne 144: Ligne 144:
  $pages_hit++;  $pages_hit++;
  unless ($page_hit{$pagenum}++) {  unless ($page_hit{$pagenum}++) {
-     $uniq_pages_hit++;+ $uniq_pages_hit++;
  }  }
  
  my $now = time;  my $now = time;
  if ($now != $last_dump) {  if ($now != $last_dump) {
-     $last_dump = $now; + $last_dump = $now; 
-     my $runtime = $now - $start; + my $runtime = $now - $start; 
-     printf("  diskchecker: running %d sec, %.02f%% coverage of %d MB (%d writes; %d/s)\n", + printf("  diskchecker: running %d sec, %.02f%% coverage of %d MB (%d writes; %d/s)\n", 
-    $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 $sock = shift; 
-     my $len; + my $len; 
-     my $rv = sysread($sock, $len, 1); + my $rv = sysread($sock, $len, 1); 
-     return undef unless $rv == 1; + return undef unless $rv == 1; 
-     my $msg; + my $msg; 
-     $rv = sysread($sock, $msg, ord($len)); + $rv = sysread($sock, $msg, ord($len)); 
-     return $msg; + return $msg; 
- }+}
  
- sub sendmsg { +sub sendmsg { 
-     my ($sock, $msg) = @_; + my ($sock, $msg) = @_; 
-     my $rv = syswrite($sock, chr(length($msg)) . $msg); + my $rv = syswrite($sock, chr(length($msg)) . $msg); 
-     my $expect = length($msg) + 1; + my $expect = length($msg) + 1; 
-     die "sendmsg failed rv=$rv, expect=$expect" unless $rv == $expect; + die "sendmsg failed rv=$rv, expect=$expect" unless $rv == $expect; 
-     return 1; + return 1; 
- }+}
  
- sub listen_mode { +sub listen_mode { 
-     my $port = shift; + my $port = shift; 
-     my $server = IO::Socket::INET->new(ReuseAddr => 1, + my $server = IO::Socket::INET->new(ReuseAddr => 1, 
-        Listen => 1, + Listen => 1, 
-        LocalPort => $port)+ LocalPort => $port)
  or die "couldn't make server socket\n";  or die "couldn't make server socket\n";
  
-     while (1) {+ while (1) {
  print "[server] diskchecker.pl: waiting for connection...\n";  print "[server] diskchecker.pl: waiting for connection...\n";
  my $sock = $server->accept()  my $sock = $server->accept()
-     or die "  die: no connection?";+ or die "  die: no connection?";
  setsockopt($sock, IPPROTO_TCP, TCP_NODELAY, pack("l", 1)) or die;  setsockopt($sock, IPPROTO_TCP, TCP_NODELAY, pack("l", 1)) or die;
  
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 $sock = shift; 
-     my $peername = getpeername($sock) or + my $peername = getpeername($sock) or 
- die "connection not there?\n"; + die "connection not there?\n"; 
-     my ($port, $iaddr) = sockaddr_in($peername); + my ($port, $iaddr) = sockaddr_in($peername); 
-     my $ip = inet_ntoa($iaddr);+ my $ip = inet_ntoa($iaddr);
  
-     my $file = "/tmp/$ip.diskchecker"; + my $file = "/tmp/$ip.diskchecker"; 
-     die "[$ip] $file is a symlink" if -l $file;+ die "[$ip] $file is a symlink" if -l $file;
  
-     print "[$ip] New connection\n";+ print "[$ip] New connection\n";
  
-     my $lines = 0; + my $lines = 0; 
-     my %state; + my %state; 
-     my $end;+ my $end;
  
-     while (1) {+ while (1) {
  if ($lines) {  if ($lines) {
-     last unless wait_for_readability(fileno($sock), 3);+ last unless wait_for_readability(fileno($sock), 3);
  }  }
  my $line = readmsg($sock);  my $line = readmsg($sock);
Ligne 224: Ligne 223:
  
  if ($line eq "read") {  if ($line eq "read") {
-     print "[$ip] Sending state info from ${ip}'s last create.\n"; + print "[$ip] Sending state info from ${ip}'s last create.\n"; 
-     open (S, "$file") or die "Couldn't open $file for reading."; + open (S, "$file") or die "Couldn't open $file for reading."; 
-     while (<S>) { + while (<S>) { 
- print $sock $_; + print $sock $_; 
-     +
-     close S; + close S; 
-     print "[$ip] Done.\n"; + print "[$ip] Done.\n"; 
-     exit 0;+ exit 0;
  }  }
  
Ligne 239: Ligne 238:
  my ($state, $pagenum, $rand) = split(/\t/, $line);  my ($state, $pagenum, $rand) = split(/\t/, $line);
  if ($state eq "pre") {  if ($state eq "pre") {
-     $state{$pagenum} = [ 0, $rand+0, $now ]; + $state{$pagenum} = [ 0, $rand+0, $now ]; 
-     sendmsg($sock, "ok");+ sendmsg($sock, "ok");
  } elsif ($state eq "post") {  } elsif ($state eq "post") {
-     $state{$pagenum} = [ 1, $rand+0, $now ];+ $state{$pagenum} = [ 1, $rand+0, $now ];
  }  }
  print "[$ip] $lines writes\n" if $lines % 1000 == 0;  print "[$ip] $lines writes\n" if $lines % 1000 == 0;
-     }+ }
  
-     print "[$ip] Writing state file...\n"; + print "[$ip] Writing state file...\n"; 
-     open (S, ">$file") or die "Couldn't open $file for writing."; + open (S, ">$file") or die "Couldn't open $file for writing."; 
-     foreach (sort { $a <=> $b } keys %state) {+ 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 "$_\t$v->[0]\t$v->[1]\t$before_end\n";  print S "$_\t$v->[0]\t$v->[1]\t$before_end\n";
-     } 
-     print "[$ip] Done.\n"; 
  }  }
 + print "[$ip] Done.\n";
 +}
  
- sub wait_for_readability { +sub wait_for_readability { 
-     my ($fileno, $timeout) = @_; + my ($fileno, $timeout) = @_; 
-     return 0 unless $fileno && $timeout;+ return 0 unless $fileno && $timeout;
  
-     my $rin; + my $rin; 
-     vec($rin, $fileno, 1) = 1; + vec($rin, $fileno, 1) = 1; 
-     my $nfound = select($rin, undef, undef, $timeout);+ my $nfound = select($rin, undef, undef, $timeout);
  
-     return 0 unless defined $nfound; + return 0 unless defined $nfound; 
-     return $nfound ? 1 : 0; + return $nfound ? 1 : 0; 
- }+} 
 +</code>
  
infrastructure/diskchecker.1536580296.txt.gz · Dernière modification : 2018/09/10 11:51 de ronan