From 500062b4e10ff5d04dbdac03a0fceb198a48f7eb Mon Sep 17 00:00:00 2001 From: Rafael Zanella Date: Wed, 16 Nov 2016 19:56:26 -0200 Subject: [PATCH] Using Commons Pool --- core/pom.xml | 5 ++ .../turn/ttorrent/common/ByteBufferPool.java | 51 +++++++++++++++++++ .../common/ByteBufferRentalService.java | 41 --------------- .../com/turn/ttorrent/common/Torrent.java | 33 ++++++------ 4 files changed, 73 insertions(+), 57 deletions(-) create mode 100644 core/src/main/java/com/turn/ttorrent/common/ByteBufferPool.java delete mode 100644 core/src/main/java/com/turn/ttorrent/common/ByteBufferRentalService.java diff --git a/core/pom.xml b/core/pom.xml index a86c7531e..5cbd931a7 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -17,6 +17,11 @@ commons-io 2.4 + + org.apache.commons + commons-pool2 + 2.4.2 + org.simpleframework simple diff --git a/core/src/main/java/com/turn/ttorrent/common/ByteBufferPool.java b/core/src/main/java/com/turn/ttorrent/common/ByteBufferPool.java new file mode 100644 index 000000000..c5e79d897 --- /dev/null +++ b/core/src/main/java/com/turn/ttorrent/common/ByteBufferPool.java @@ -0,0 +1,51 @@ +package com.turn.ttorrent.common; + +import org.apache.commons.pool2.BasePooledObjectFactory; +import org.apache.commons.pool2.PooledObject; +import org.apache.commons.pool2.impl.DefaultPooledObject; +import org.apache.commons.pool2.impl.GenericObjectPool; +import org.apache.commons.pool2.impl.GenericObjectPoolConfig; + +import java.nio.ByteBuffer; + +public class ByteBufferPool { + + private final GenericObjectPool pool; + + public GenericObjectPool getPool() { + return pool; + } + + public ByteBufferPool(int amount, int length) { + final GenericObjectPoolConfig gopc = new GenericObjectPoolConfig(); + gopc.setMinIdle(amount); + gopc.setMaxTotal(amount); + + pool = new GenericObjectPool(new ByteBufferFactory(length), gopc); + } + + private class ByteBufferFactory extends BasePooledObjectFactory { + private final int length; + + private ByteBufferFactory(int length) { + super(); + + this.length = length; + } + + @Override + public ByteBuffer create() { + return ByteBuffer.allocate(length); + } + + @Override + public PooledObject wrap(ByteBuffer buffer) { + return new DefaultPooledObject(buffer); + } + + @Override + public void passivateObject(PooledObject pooledObject) { + pooledObject.getObject().clear(); + } + } +} diff --git a/core/src/main/java/com/turn/ttorrent/common/ByteBufferRentalService.java b/core/src/main/java/com/turn/ttorrent/common/ByteBufferRentalService.java deleted file mode 100644 index f217cc845..000000000 --- a/core/src/main/java/com/turn/ttorrent/common/ByteBufferRentalService.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.turn.ttorrent.common; - -import java.nio.ByteBuffer; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; - -/** - * A limited, exclusive storage, so that the workers are limited to it's amount. - * - * The ByteBuffers are array backed, so the APIs they get sent to have no need to instantiate one - * - * "rental service": exemplifies well the intent, shitty name :-) - * - */ -public class ByteBufferRentalService { - private BlockingQueue byteBufferBlockingQueue; - - /** - * Initializes a bounded storage - * - * @param amount the amount of byte buffers to create - * @param length the length of the created buffers - */ - public ByteBufferRentalService(int amount, int length) { - byteBufferBlockingQueue = new LinkedBlockingQueue(amount); - - for (int i = 0; i < amount; i++) { - byteBufferBlockingQueue.add( ByteBuffer.allocate(length) ); - } - } - - public ByteBuffer take() throws InterruptedException { - return byteBufferBlockingQueue.take(); - } - - public void put(ByteBuffer buffer) throws InterruptedException { - buffer.clear(); - - byteBufferBlockingQueue.put( buffer ); - } -} diff --git a/core/src/main/java/com/turn/ttorrent/common/Torrent.java b/core/src/main/java/com/turn/ttorrent/common/Torrent.java index b007e6296..11add5c29 100644 --- a/core/src/main/java/com/turn/ttorrent/common/Torrent.java +++ b/core/src/main/java/com/turn/ttorrent/common/Torrent.java @@ -505,7 +505,7 @@ public static Torrent load(File torrent, boolean seeder) * torrent's creator. */ public static Torrent create(File source, URI announce, String createdBy) - throws InterruptedException, IOException, NoSuchAlgorithmException { + throws InterruptedException, IOException, NoSuchAlgorithmException, Exception { return Torrent.create(source, null, DEFAULT_PIECE_LENGTH, announce, null, createdBy); } @@ -528,7 +528,7 @@ public static Torrent create(File source, URI announce, String createdBy) * torrent's creator. */ public static Torrent create(File parent, List files, URI announce, - String createdBy) throws InterruptedException, IOException, NoSuchAlgorithmException { + String createdBy) throws InterruptedException, IOException, NoSuchAlgorithmException, Exception { return Torrent.create(parent, files, DEFAULT_PIECE_LENGTH, announce, null, createdBy); } @@ -549,7 +549,7 @@ public static Torrent create(File parent, List files, URI announce, * torrent's creator. */ public static Torrent create(File source, int pieceLength, List> announceList, - String createdBy) throws InterruptedException, IOException, NoSuchAlgorithmException { + String createdBy) throws InterruptedException, IOException, NoSuchAlgorithmException, Exception { return Torrent.create(source, null, pieceLength, null, announceList, createdBy); } @@ -574,7 +574,7 @@ public static Torrent create(File source, int pieceLength, List> annou */ public static Torrent create(File source, List files, int pieceLength, List> announceList, String createdBy) - throws InterruptedException, IOException, NoSuchAlgorithmException { + throws InterruptedException, IOException, NoSuchAlgorithmException, Exception { return Torrent.create(source, files, pieceLength, null, announceList, createdBy); } @@ -600,7 +600,7 @@ public static Torrent create(File source, List files, int pieceLength, */ private static Torrent create(File parent, List files, int pieceLength, URI announce, List> announceList, String createdBy) - throws InterruptedException, IOException, NoSuchAlgorithmException { + throws InterruptedException, IOException, NoSuchAlgorithmException, Exception { if (files == null || files.isEmpty()) { logger.info("Creating single-file torrent for {}...", parent.getName()); @@ -676,16 +676,16 @@ private static class CallableChunkHasher implements Callable { private final MessageDigest md; private final ByteBuffer data; - private final ByteBufferRentalService bbrs; + private final ByteBufferPool bbp; - CallableChunkHasher(ByteBuffer rentedBuffer, ByteBufferRentalService bbrs) throws NoSuchAlgorithmException { + CallableChunkHasher(ByteBuffer rentedBuffer, ByteBufferPool bbp) throws NoSuchAlgorithmException { this.md = MessageDigest.getInstance("SHA-1"); rentedBuffer.mark(); rentedBuffer.reset(); this.data = rentedBuffer; - this.bbrs = bbrs; + this.bbp = bbp; } @Override @@ -693,7 +693,7 @@ public String call() throws UnsupportedEncodingException, InterruptedException { this.md.reset(); this.md.update(this.data); - bbrs.put( this.data ); + this.bbp.getPool().returnObject(this.data); return new String(md.digest(), Torrent.BYTE_ENCODING); } @@ -715,15 +715,15 @@ public String call() throws UnsupportedEncodingException, InterruptedException { * @param file The file to hash. */ private static String hashFile(File file, int pieceLenght) - throws InterruptedException, IOException, NoSuchAlgorithmException { + throws InterruptedException, IOException, NoSuchAlgorithmException, Exception { return Torrent.hashFiles(Arrays.asList(new File[] { file }), pieceLenght); } private static String hashFiles(List files, int pieceLenght) - throws InterruptedException, IOException, NoSuchAlgorithmException { + throws InterruptedException, IOException, NoSuchAlgorithmException, Exception { int threads = getHashingThreadsCount(); ExecutorService executor = Executors.newFixedThreadPool(threads); - final ByteBufferRentalService bbrs = new ByteBufferRentalService(threads + 1, pieceLenght); + final ByteBufferPool bbp = new ByteBufferPool(threads + 1, pieceLenght); List> results = new LinkedList>(); StringBuilder hashes = new StringBuilder(); @@ -748,13 +748,14 @@ private static String hashFiles(List files, int pieceLenght) int step = 10; try { - buffer = bbrs.take(); + buffer = bbp.getPool().borrowObject(); while (channel.read(buffer) > 0) { if (buffer.remaining() == 0) { buffer.clear(); - results.add(executor.submit(new CallableChunkHasher(buffer, bbrs))); - buffer = bbrs.take(); + results.add(executor.submit(new CallableChunkHasher(buffer, bbp))); + + buffer = bbp.getPool().borrowObject(); } if (results.size() >= threads) { @@ -776,7 +777,7 @@ private static String hashFiles(List files, int pieceLenght) if ((buffer != null) && (buffer.position() > 0)) { buffer.limit(buffer.position()); buffer.position(0); - results.add(executor.submit(new CallableChunkHasher(buffer, bbrs))); + results.add(executor.submit(new CallableChunkHasher(buffer, bbp))); } pieces += accumulateHashes(hashes, results);