@@ -168,6 +168,15 @@ public enum Counter {
168
168
BYTES_COPIED
169
169
}
170
170
171
+ /**
172
+ * Indicates the checksum comparison result.
173
+ */
174
+ public enum ChecksumComparison {
175
+ TRUE , // checksum comparison is compatible and true.
176
+ FALSE , // checksum comparison is compatible and false.
177
+ INCOMPATIBLE , // checksum comparison is not compatible.
178
+ }
179
+
171
180
private static class ExportMapper
172
181
extends Mapper <BytesWritable , NullWritable , NullWritable , NullWritable > {
173
182
private static final Logger LOG = LoggerFactory .getLogger (ExportMapper .class );
@@ -533,6 +542,9 @@ private FileChecksum getFileChecksum(final FileSystem fs, final Path path) {
533
542
}
534
543
}
535
544
545
+ /**
546
+ * Utility to compare the file length and checksums for the paths specified.
547
+ */
536
548
private void verifyCopyResult (final FileStatus inputStat , final FileStatus outputStat )
537
549
throws IOException {
538
550
long inputLen = inputStat .getLen ();
@@ -547,20 +559,64 @@ private void verifyCopyResult(final FileStatus inputStat, final FileStatus outpu
547
559
548
560
// If length==0, we will skip checksum
549
561
if (inputLen != 0 && verifyChecksum ) {
550
- FileChecksum inChecksum = getFileChecksum (inputFs , inputPath );
551
- if (inChecksum == null ) {
552
- LOG .warn ("Input file " + inputPath + " checksums are not available" );
553
- }
554
- FileChecksum outChecksum = getFileChecksum (outputFs , outputPath );
555
- if (outChecksum == null ) {
556
- LOG .warn ("Output file " + outputPath + " checksums are not available" );
557
- }
558
- if (inChecksum != null && outChecksum != null && !inChecksum .equals (outChecksum )) {
559
- throw new IOException ("Checksum mismatch between " + inputPath + " and " + outputPath );
562
+ FileChecksum inChecksum = getFileChecksum (inputFs , inputStat .getPath ());
563
+ FileChecksum outChecksum = getFileChecksum (outputFs , outputStat .getPath ());
564
+
565
+ ChecksumComparison checksumComparison = verifyChecksum (inChecksum , outChecksum );
566
+ if (!checksumComparison .equals (ChecksumComparison .TRUE )) {
567
+ StringBuilder errMessage = new StringBuilder ("Checksum mismatch between " )
568
+ .append (inputPath ).append (" and " ).append (outputPath ).append ("." );
569
+
570
+ boolean addSkipHint = false ;
571
+ String inputScheme = inputFs .getScheme ();
572
+ String outputScheme = outputFs .getScheme ();
573
+ if (!inputScheme .equals (outputScheme )) {
574
+ errMessage .append (" Input and output filesystems are of different types.\n " )
575
+ .append ("Their checksum algorithms may be incompatible." );
576
+ addSkipHint = true ;
577
+ } else if (inputStat .getBlockSize () != outputStat .getBlockSize ()) {
578
+ errMessage .append (" Input and output differ in block-size." );
579
+ addSkipHint = true ;
580
+ } else if (
581
+ inChecksum != null && outChecksum != null
582
+ && !inChecksum .getAlgorithmName ().equals (outChecksum .getAlgorithmName ())
583
+ ) {
584
+ errMessage .append (" Input and output checksum algorithms are of different types." );
585
+ addSkipHint = true ;
586
+ }
587
+ if (addSkipHint ) {
588
+ errMessage
589
+ .append (" You can choose file-level checksum validation via "
590
+ + "-Ddfs.checksum.combine.mode=COMPOSITE_CRC when block-sizes"
591
+ + " or filesystems are different." )
592
+ .append (" Or you can skip checksum-checks altogether with --no-checksum-verify.\n " )
593
+ .append (" (NOTE: By skipping checksums, one runs the risk of "
594
+ + "masking data-corruption during file-transfer.)\n " );
595
+ }
596
+ throw new IOException (errMessage .toString ());
560
597
}
561
598
}
562
599
}
563
600
601
+ /**
602
+ * Utility to compare checksums
603
+ */
604
+ private ChecksumComparison verifyChecksum (final FileChecksum inChecksum ,
605
+ final FileChecksum outChecksum ) {
606
+ // If the input or output checksum is null, or the algorithms of input and output are not
607
+ // equal, that means there is no comparison
608
+ // and return not compatible. else if matched, return compatible with the matched result.
609
+ if (
610
+ inChecksum == null || outChecksum == null
611
+ || !inChecksum .getAlgorithmName ().equals (outChecksum .getAlgorithmName ())
612
+ ) {
613
+ return ChecksumComparison .INCOMPATIBLE ;
614
+ } else if (inChecksum .equals (outChecksum )) {
615
+ return ChecksumComparison .TRUE ;
616
+ }
617
+ return ChecksumComparison .FALSE ;
618
+ }
619
+
564
620
/**
565
621
* Check if the two files are equal by looking at the file length, and at the checksum (if user
566
622
* has specified the verifyChecksum flag).
0 commit comments