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);