/*
* Copyright 2008-2009 LinkedIn, Inc
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package voldemort.store.readonly.checksum;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
import java.util.Comparator;
import junit.framework.TestCase;
import voldemort.store.readonly.checksum.CheckSum.CheckSumType;
import voldemort.utils.ByteUtils;
public class CheckSumTests extends TestCase {
public void testCheckSum() {
CheckSum instance = CheckSum.getInstance("blah");
assertNull(instance);
CheckSum instance2 = CheckSum.getInstance("md5");
assertNotNull(instance2);
CheckSum instance3 = CheckSum.getInstance("crc32");
assertNotNull(instance3);
CheckSum instance4 = CheckSum.getInstance("adler32");
assertNotNull(instance4);
byte[] emptyBytes = new byte[0];
instance2.update(emptyBytes);
assertNotNull(instance2.getCheckSum());
assertEquals(instance2.getCheckSum().length, CheckSum.checkSumLength(CheckSumType.MD5));
instance3.update(emptyBytes);
assertNotNull(instance3.getCheckSum());
assertEquals(instance3.getCheckSum().length, CheckSum.checkSumLength(CheckSumType.CRC32));
instance4.update(emptyBytes);
assertNotNull(instance4.getCheckSum());
assertEquals(instance4.getCheckSum().length, CheckSum.checkSumLength(CheckSumType.ADLER32));
}
/**
* Calculates the checksum of checksums of individual files.
*
* @param files The files whose bytes to read
* @param checkSumType
* @return bytes
*/
public static byte[] calculateCheckSum(File[] files, CheckSumType checkSumType)
throws Exception {
CheckSum checkSumGenerator = CheckSum.getInstance(checkSumType);
CheckSum fileCheckSumGenerator = CheckSum.getInstance(checkSumType);
int bufferSize = 64 * 1024;
byte[] buffer = new byte[bufferSize];
Arrays.sort(files, new Comparator<File>() {
public int compare(File fs1, File fs2) {
// directories before files
if(fs1.isDirectory())
return fs2.isDirectory() ? 0 : -1;
if(fs2.isDirectory())
return fs1.isDirectory() ? 0 : 1;
String f1 = fs1.getName(), f2 = fs2.getName();
// All checksum files given priority
if(f1.endsWith("metadata"))
return -1;
if(f2.endsWith("metadata"))
return 1;
// if both same, lexicographically
if((f1.endsWith(".index") && f2.endsWith(".index"))
|| (f1.endsWith(".data") && f2.endsWith(".data"))) {
return f1.compareToIgnoreCase(f2);
}
if(f1.endsWith(".index")) {
return 1;
} else {
return -1;
}
}
});
for(File file: files) {
if(file.isFile() && !file.getName().startsWith(".")
&& !file.getName().contains("checkSum.txt") && !file.getName().contains("metadata")) {
DataInputStream is;
try {
is = new DataInputStream(new FileInputStream(file));
} catch(FileNotFoundException e) {
continue;
}
try {
while(true) {
int read = is.read(buffer);
if(read < 0)
break;
else if(read < bufferSize) {
buffer = ByteUtils.copy(buffer, 0, read);
}
fileCheckSumGenerator.update(buffer);
}
is.close();
} catch(IOException e) {
break;
}
checkSumGenerator.update(fileCheckSumGenerator.getCheckSum());
}
}
return checkSumGenerator.getCheckSum();
}
}