package org.torrent.internal.util;
import java.io.IOException;
import java.util.Arrays;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.logging.Logger;
import org.torrent.internal.data.TorrentMetaInfo;
import org.torrent.internal.data.Hash;
import org.torrent.internal.io.DataReader;
import org.torrent.internal.io.DigesterService;
import org.torrent.internal.io.PieceEvent;
import org.torrent.internal.io.PieceVerifier;
import org.torrent.internal.io.DigesterService.CheckCallback;
import org.torrent.internal.io.DigesterService.CheckRequest;
public class BTUtil {
private static final Logger LOG = Logger.getLogger(BTUtil.class.getName());
private static ExecutorService dispatcher = Executors
.newSingleThreadExecutor(new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r, "BT Event dispatcher");
t.setDaemon(true);
return t;
}
});
/*
* Requests that some code be executed in the event-dispatching thread.
* This method returns immediately, without waiting for the code to execute.
*/
public static void invokeLater(final Runnable run) {
dispatcher.execute(new Runnable() {
@Override
public void run() {
Time time = new Time();
run.run();
if (time.delta() > 200) {
LOG.finer(run + " took " + time.delta() + " to complete!");
}
}
});
}
/*
* Acts like invokeLater(), except that this method waits
* for the code to execute. As a rule, you should use invokeLater()
* instead of this method.
*/
public static <T> T invokeAndWait(Callable<T> callable) throws Exception {
return dispatcher.submit(callable).get();
}
public static PieceVerifier createPieceVerifier(
final TorrentMetaInfo contentInfo, final DigesterService digester,
final DataReader reader) {
return new PieceVerifier() {
@Override
public void checkPiece(final TorrentMetaInfo.Piece piece) {
digester.requestCheck(new CheckRequest(reader,
piece.getStart(), piece.getLength(),
new CheckCallback() {
@Override
public void caughtException(IOException e) {
fireCaughtException(new PieceEvent(
BTUtil.class, e, piece));
}
@Override
public void resultDigest(byte[] digest) {
Hash res = new Hash(digest, Hash.Type.SHA1);
if (Arrays.equals(digest, piece.getHash()
.toByteArray())) {
firePieceVerified(new PieceEvent(
BTUtil.class, piece, res));
} else {
firePieceFalsified(new PieceEvent(
BTUtil.class, piece, res));
}
}
}));
}
};
}
}