[h1]DCCF :: Disk Copy, Compare & Fill (Disk Data Integrity Full Access Test)[/h1]
I wrote this perl script around 2006,
this script is trying to "Filled the whole disk(partition) with 2-pass compare"
Which I believe this could verify the data integrity both within Caches and already-on-the-disk.
Note:
(1) Only tested in Windows, yet it might be not hard to port to other platforms.
(2) I remember I revised this to "multiple-threaded version" around 2007;
I may need to spare some more time to find it out.
代碼:
#!C:/perl/bin/perl.exe
################################################################################
### DCCF :: Disk Copy, Compare & Fill Test Utility (Single Thread Version)
###
### Author :: Type T.H.Wu @ 2006
###
### Desc: Perl Storage/Disk Test Utility
### It will (1) Generate source
### (2) Copy source to target
### (3) Compare source vs target
### (4) (Disk Full) Re-compare again all files
### (5) Finally, delete all target files
###
################################################################################
use File::Copy qw(copy);
use File::Compare qw(compare);
use File::Glob ':glob';
use Getopt::Std;
use Win32:😃riveInfo qw(DriveSpace);
# flush immediately
$| = 1;
$thread_should_stop = 0;
# SIG
sub sig_flush()
{
my $signame = shift;
$thread_should_stop = 1;
print $/."Got Signaled: SIG$signame, Try stopping...".$/;
sleep(5);
die("Terminated");
}
### $SIG{INT} = \&sig_flush;
sub print_usage()
{
print "CCF :: Copy Compare Fill".$/.$/."Usage:".$/;
print " -a: Activity. Default = 0".$/;
print " -a 0 ==> Compare after each Copy.".$/;
print " -a 1 ==> Compare all after fill done.".$/;
print " -b: Buffer used for copy & compare, in MB. Default = 8 MB each".$/;
print " -d: Directory to test on. Mandatory, e.g. -d C:".$/;
print " -l: Loop. Default = 1. Set 0 for infinite.".$/;
print " -u: Unit size. In Bytes. Default = 1023 bytes(1KB-1).".$/;
print " -s: Size(*Unit) to test. Default = 8192.".$/;
print " So, we will test around 8M 4M ... 2K-1 by default.".$/;
print $/;
print "Example: dccf -d g: -b 16 -s 32".$/;
}
sub handle_opt()
{
getopt('abdlusp');
$par_dir = $opt_d;
if ($par_dir eq "")
{
print_usage();
exit(-1);
}
$drv_buf = substr($par_dir,0,1);
$par_buff = $opt_b;
$par_size = $opt_s;
$par_unit = $opt_u;
}
sub init_parameter()
{
$par_buff = 8 if ($par_buff eq ""); # -b
$par_size = 16*1024 if ($par_size eq ""); # -s
$par_loop = 1 if ($par_loop eq ""); # -l
$par_unit = 1023 if ($par_unit eq ""); # -u
### TODO
$par_loop = 0;
$par_ptn = 1;
$par_act = 0;;
$buffsize = $par_unit * $par_buff;
print "CCF Using: Dir=".$par_dir." Size=".$par_size." Buff=".$par_buff.$/;
}
sub clean_up()
{
@list = bsd_glob($par_dir.'*SRC*');
unlink(@list);
@list = bsd_glob($par_dir.'*TMP*');
unlink(@list);
@list = bsd_glob($par_dir.'*TGT*');
unlink(@list);
}
sub gen_ptnf1()
{
$tmpfil = "TMP";
$p = $par_dir.$tmpfil;
@tgtnew = {};
@srcorg = {};
@srcsize = {};
$srccnt = 0;
for ($i=$par_size; $i>=1; $i=int($i/2))
{
$srcsize[$srccnt] = $i;
$srcorg[$srccnt] = $par_dir."SRC-".$i;
$srcname[$srccnt] = "SRC-".$i;
$tgtnew[$srccnt] = $par_dir."TGT-".$i;
$tgtname[$srccnt] = "TGT-".$i;
$srccnt++;
print $srcsize[$srccnt-1].": ".$srcorg[$srccnt-1].$/;
}
}
sub gen_ptnf2()
{
my @tmpstr = {};
my $buf = "";
my $cnt = 0;
for ($i = 0; $i < $par_unit; $i++)
{
$buf .= chr(int(rand(255)));
if (($i % 127))
{
$tmpstr[$cnt++] = $buf;
$buf = "";
}
}
if ($buf ne "") {
$tmpstr[$cnt++] = $buf;
}
for ($n = 0; $n < $srccnt; $n++)
{
my $sz = $srcsize[$n];
my $sf = $srcorg[$n];
print "Initialing SRC-".$sz." ";
open (FH, ">>$sf") or die($!);
for ($i=0; $i < $sz; $i++)
{
print FH @tmpstr;
print "." if ((int($sz/10)) > 0 and ($i % (int($sz/10))) == 0);
}
close(FH);
print $/;
}
print "Done SRC file initializing".$/;
}
sub init()
{
handle_opt();
init_parameter();
clean_up();
gen_ptnf1();
gen_ptnf2();
}
################################################################ MAIN
init();
$fill = 1;
$cnt_file = 0;
$cnt_all = 0;
$cnt_overall = 0;
print "[0] ".(localtime).$/;
do {
while (($fill == 1) and ($thread_should_stop == 0))
{
my $tt = $par_dir.("0" x ( 10 - length("".$cnt_all) ) . $cnt_all)."-".$tgtname[$cnt_file];
my $ss = $srcorg[$cnt_file];
my $fspc;
print "[".$cnt_overall."] Copy ".$ss." -> ".$tt." ... ";
$fill = copy($ss, $tt, $buffsize);
if ($fill == 1)
{
print "Done".$/."[".$cnt_overall."] Compare ... ";
if (compare($ss, $tt, $buffsize) == 0)
{ print "Equal".$/; }
else
{ die("================================= NOT Equal! Stop"); }
$cnt_overall++;
$cnt_file++;
$cnt_all++;
$cnt_file = $cnt_file % $srccnt;
}
print "[".($cnt_overall-1)."] -------------------------------------------- ".(localtime).$/;
################ Check Free Space
$fspc = (Win32:😃riveInfo:😃riveSpace($drv_buf))[6];
$aspc = $srcsize[$cnt_file] * 3 * $par_unit;
if ($aspc > $fspc) {
print "==================================== FULL! No more free space ... ".$fspc.$/;
print "Stop copy and re-compare".$/;
for ($i = 0; $i < $cnt_all; $i++) {
$tt = $par_dir.("0" x ( 10 - length("".$i) ) . $i)."-".$tgtname[$i % $srccnt];
$ss = $srcorg[$i % $srccnt];
######### Compare Again
print "[".$cnt_overall."] Re-Compare ... ".$tt." ";
if (compare($ss, $tt, $buffsize) == 0)
{ print "Equal (".$i."/".$cnt_all.")".$/; }
else
{ die("================================= NOT Equal! Stop"); }
######### Delete
print "[".$cnt_overall."] Delete it.".$/;
unlink $tt or die("=========== UNABLE TO DELETE FILE!".$/);
print "[".($cnt_overall-1)."] -------------------------------------------- ".(localtime).$/;
}
######### Reset
$cnt_file = 0;
$cnt_all = 0;
$fspc = (Win32:😃riveInfo:😃riveSpace($drv_buf))[6];
print "==================================== Done Unlink ALL. Free space ... ".$fspc.$/;
print "==================================== Prepare to launch New Interation on (".$drv_buf.")!".$/;
}
else
{
print "[".$cnt_overall."] Free space of ".$drv_buf." = ".int($aspc/$par_unit)."/".int($fspc/$par_unit)."".$/;
}
}
$par_loop--;
} while (($par_loop != 0) and ($thread_should_stop == 0));
exit(1);
################################################################ END MAIN
(2014-07-28 17:11)