/*
* Copyright 2004 - 2008 Christian Sprajc, Dennis Waldherr. All rights reserved.
*
* This file is part of PowerFolder.
*
* PowerFolder is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation.
*
* PowerFolder is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PowerFolder. If not, see <http://www.gnu.org/licenses/>.
*
* $Id: AbstractDownloadManager.java 5151 2008-09-04 21:50:35Z bytekeeper $
*/
package de.dal33t.powerfolder.transfer.swarm;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.Adler32;
import de.dal33t.powerfolder.Controller;
import de.dal33t.powerfolder.light.FileInfo;
import de.dal33t.powerfolder.util.ProgressListener;
import de.dal33t.powerfolder.util.Reject;
import de.dal33t.powerfolder.util.delta.FilePartsRecord;
import de.dal33t.powerfolder.util.delta.FilePartsRecordBuilder;
import de.schlichtherle.truezip.file.TFileInputStream;
/**
* Abstract {@link FileRecordProvider} which can compute {@link FilePartsRecord}
* s based on {@link FileInfo}s.
*
* @author Dennis "Bytekeeper" Waldherr
*/
public abstract class AbstractFileRecordProvider implements FileRecordProvider {
private static final Logger log = Logger
.getLogger(AbstractFileRecordProvider.class.getName());
private Controller controller;
/**
* @param controller
*/
public AbstractFileRecordProvider(Controller controller) {
Reject.ifNull(controller, "Controller is null!");
this.controller = controller;
}
public Controller getController() {
return controller;
}
protected FilePartsRecord computeFilePartsRecord(FileInfo fileInfo,
ProgressListener obs) throws IOException
{
assert fileInfo != null;
long start = System.currentTimeMillis();
File f = fileInfo.getDiskFile(controller.getFolderRepository());
// TODO: Both, the RecordBuilder and the Matcher use "almost"
// the same algorithms, there should be a shared config.
// TODO: To select a part size I just took 4Gb as size and
// wanted the result to be ~512kb.
// But there should be a more thorough investigation on how to
// calculate it.
int partSize = Math
.max(4096, (int) (Math.pow(f.length(), 0.25) * 2048));
InputStream in = new TFileInputStream(f);
try {
FilePartsRecordBuilder b = new FilePartsRecordBuilder(
new Adler32(), MessageDigest.getInstance("SHA-256"),
MessageDigest.getInstance("MD5"), partSize);
int read = 0;
byte buf[] = new byte[8192];
long processed = 0, size = f.length();
while ((read = in.read(buf)) > 0) {
b.update(buf, 0, read);
if (obs != null) {
obs.progressReached((double) processed / size);
processed += read;
}
}
FilePartsRecord fileRecord = b.getRecord();
long took = System.currentTimeMillis() - start;
if (log.isLoggable(Level.FINE)) {
log.fine("Built file parts for " + this + ". took " + took
+ "ms" + " while processing " + processed + " bytes.");
}
return fileRecord;
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
} finally {
in.close();
}
}
}