style changes

- remove extraneous isDebugEnabled() checks;
- rename some params for better readability;
- decrease number of if-else blocks;
- fix some typos.
This commit is contained in:
laur 2022-09-02 19:16:31 +02:00
parent a58ab74db5
commit 7fe610ce6a
46 changed files with 149 additions and 264 deletions

View file

@ -48,7 +48,7 @@ By default the web-ui is disabled, you can enable it with some more arguments:
- `--joal.ui.secret-token="SECRET_TOKEN"`: use your own secret token here (this is some kind of a password, choose a complicated one). - `--joal.ui.secret-token="SECRET_TOKEN"`: use your own secret token here (this is some kind of a password, choose a complicated one).
Once joal is started head to: `http://localhost:port/SECRET_OBFUSCATION_PATH/ui/` (obviously, replace `SECRET_OBFUSCATION_PATH`) by the value you had chosen Once joal is started head to: `http://localhost:port/SECRET_OBFUSCATION_PATH/ui/` (obviously, replace `SECRET_OBFUSCATION_PATH`) by the value you had chosen
The `joal.ui.path.prefix` might seems useless but it's actually **crucial** to set it as complex as possible to prevent peoples to know that joal is running on your server. The `joal.ui.path.prefix` might seems useless but it's actually **crucial** to set it as complex as possible to prevent people to know that joal is running on your server.
If you want to use iframe you may also pass the `joal.iframe.enabled=true` argument. If you don't known what that is just ignore it. If you want to use iframe you may also pass the `joal.iframe.enabled=true` argument. If you don't known what that is just ignore it.
@ -135,7 +135,7 @@ Those projects are maintained by their individual authors, if you have any quest
# Thanks: # Thanks:
This project use a modified version of the awesome [mpetazzoni/ttorrent](http://mpetazzoni.github.com/ttorrent/) library. Thanks to **mpetazzoni** for this. This project use a modified version of the awesome [mpetazzoni/ttorrent](http://mpetazzoni.github.com/ttorrent/) library. Thanks to **mpetazzoni** for this.
Also this project has benefited from the help of several peoples, see [Thanks.md](THANKS.md) Also this project has benefited from the help of several people, see [Thanks.md](THANKS.md)
## Supporters ## Supporters
[![Thanks for providing Jetbrain license](readme-assets/jetbrains.svg)](https://www.jetbrains.com/?from=joal) [![Thanks for providing Jetbrain license](readme-assets/jetbrains.svg)](https://www.jetbrains.com/?from=joal)

View file

@ -1,7 +1,6 @@
package org.araymond.joal; package org.araymond.joal;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration;
@ -15,5 +14,4 @@ public class JackOfAllTradesApplication {
public static void main(final String[] args) { public static void main(final String[] args) {
SpringApplication.run(JackOfAllTradesApplication.class, args); SpringApplication.run(JackOfAllTradesApplication.class, args);
} }
}
}

View file

@ -24,7 +24,6 @@ public class CoreEventListener {
public CoreEventListener() { public CoreEventListener() {
} }
@Async @Async
@Order(Ordered.HIGHEST_PRECEDENCE) @Order(Ordered.HIGHEST_PRECEDENCE)
@EventListener @EventListener

View file

@ -1,7 +1,6 @@
package org.araymond.joal.core; package org.araymond.joal.core;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Maps;
import org.apache.http.config.SocketConfig; import org.apache.http.config.SocketConfig;
import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.client.HttpClients;
@ -38,10 +37,7 @@ import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.nio.file.StandardOpenOption; import java.nio.file.StandardOpenOption;
import java.util.ArrayList; import java.util.*;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
/** /**
@ -168,17 +164,11 @@ public class SeedManager {
} }
public List<AnnouncerFacade> getCurrentlySeedingAnnouncer() { public List<AnnouncerFacade> getCurrentlySeedingAnnouncer() {
if (this.client == null) { return this.client == null ? new ArrayList<>() : client.getCurrentlySeedingAnnouncer();
return new ArrayList<>();
}
return client.getCurrentlySeedingAnnouncer();
} }
public Map<InfoHash, Speed> getSpeedMap() { public Map<InfoHash, Speed> getSpeedMap() {
if (this.bandwidthDispatcher == null) { return this.bandwidthDispatcher == null ? new HashMap<>() : bandwidthDispatcher.getSpeedMap();
return Maps.newHashMap();
}
return bandwidthDispatcher.getSpeedMap();
} }
public AppConfiguration getCurrentConfig() { public AppConfiguration getCurrentConfig() {

View file

@ -1,8 +1,6 @@
package org.araymond.joal.core.bandwith; package org.araymond.joal.core.bandwith;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.araymond.joal.core.bandwith.weight.PeersAwareWeightCalculator; import org.araymond.joal.core.bandwith.weight.PeersAwareWeightCalculator;
import org.araymond.joal.core.bandwith.weight.WeightHolder; import org.araymond.joal.core.bandwith.weight.WeightHolder;
@ -10,10 +8,13 @@ import org.araymond.joal.core.torrent.torrent.InfoHash;
import org.slf4j.Logger; import org.slf4j.Logger;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock;
import static java.util.Optional.ofNullable;
import static org.apache.commons.lang3.ObjectUtils.getIfNull;
import static org.slf4j.LoggerFactory.getLogger; import static org.slf4j.LoggerFactory.getLogger;
public class BandwidthDispatcher implements BandwidthDispatcherFacade, Runnable { public class BandwidthDispatcher implements BandwidthDispatcherFacade, Runnable {
@ -25,8 +26,8 @@ public class BandwidthDispatcher implements BandwidthDispatcherFacade, Runnable
private final Map<InfoHash, Speed> speedMap; private final Map<InfoHash, Speed> speedMap;
private SpeedChangedListener speedChangedListener; private SpeedChangedListener speedChangedListener;
private final int threadPauseInterval; private final int threadPauseInterval;
private int threadLoopCounter = 0; private int threadLoopCounter;
private volatile boolean stop = false; private volatile boolean stop;
private Thread thread; private Thread thread;
public BandwidthDispatcher(final int threadPauseInterval, final RandomSpeedProvider randomSpeedProvider) { public BandwidthDispatcher(final int threadPauseInterval, final RandomSpeedProvider randomSpeedProvider) {
@ -35,7 +36,6 @@ public class BandwidthDispatcher implements BandwidthDispatcherFacade, Runnable
this.speedMap = new HashMap<>(); this.speedMap = new HashMap<>();
this.lock = new ReentrantReadWriteLock(); this.lock = new ReentrantReadWriteLock();
this.weightHolder = new WeightHolder<>(new PeersAwareWeightCalculator()); this.weightHolder = new WeightHolder<>(new PeersAwareWeightCalculator());
this.randomSpeedProvider = randomSpeedProvider; this.randomSpeedProvider = randomSpeedProvider;
} }
@ -44,19 +44,18 @@ public class BandwidthDispatcher implements BandwidthDispatcherFacade, Runnable
this.speedChangedListener = speedListener; this.speedChangedListener = speedListener;
} }
/* /**
* This method does not benefit from the lock, because the value will never be accessed in a ambiguous way. * This method does not benefit from the lock, because the value will never be accessed in a ambiguous way.
* And even if it happens, we returns 0 by default. * And even if it happens, we return 0 by default.
*/ */
public TorrentSeedStats getSeedStatForTorrent(final InfoHash infoHash) { public TorrentSeedStats getSeedStatForTorrent(final InfoHash infoHash) {
final TorrentSeedStats torrentSeedStats = this.torrentsSeedStats.get(infoHash); return getIfNull(this.torrentsSeedStats.get(infoHash), TorrentSeedStats::new);
return torrentSeedStats == null ? new TorrentSeedStats() : torrentSeedStats;
} }
public Map<InfoHash, Speed> getSpeedMap() { public Map<InfoHash, Speed> getSpeedMap() {
try { try {
this.lock.readLock().lock(); this.lock.readLock().lock();
return Maps.newHashMap(speedMap); return new HashMap<>(speedMap);
} finally { } finally {
this.lock.readLock().unlock(); this.lock.readLock().unlock();
} }
@ -90,16 +89,17 @@ public class BandwidthDispatcher implements BandwidthDispatcherFacade, Runnable
this.threadLoopCounter = 0; this.threadLoopCounter = 0;
} }
// This method as to run as fast as possible to avoid blocking other ones. Because we wan't this loop // This method as to run as fast as possible to avoid blocking other ones. Because we wasn't this loop
// to be scheduled as precise as we can. Locking to much will delay the Thread.sleep and cause stats // to be scheduled as precise as we can. Locking too much will delay the Thread.sleep and cause stats
// to be undervalued // to be undervalued
this.lock.readLock().lock(); this.lock.readLock().lock();
final Set<Map.Entry<InfoHash, TorrentSeedStats>> entrySet = Sets.newHashSet(this.torrentsSeedStats.entrySet()); final Set<Map.Entry<InfoHash, TorrentSeedStats>> entrySet = new HashSet<>(this.torrentsSeedStats.entrySet());
this.lock.readLock().unlock(); this.lock.readLock().unlock();
for (final Map.Entry<InfoHash, TorrentSeedStats> entry : entrySet) { for (final Map.Entry<InfoHash, TorrentSeedStats> entry : entrySet) {
final Speed speed = this.speedMap.get(entry.getKey()); final long speedInBytesPerSecond = ofNullable(this.speedMap.get(entry.getKey()))
final long speedInBytesPerSecond = speed == null ? 0: speed.getBytesPerSeconds(); // avoid Map#getOrDefault as it will trigger a lot of Speed object instantiation for nothing. .map(Speed::getBytesPerSeconds)
.orElse(0L);
// Divide by 1000 because of the thread pause interval being in milliseconds // Divide by 1000 because of the thread pause interval being in milliseconds
// The multiplication HAS to be done before the division, otherwise we're going to have trailing zeroes // The multiplication HAS to be done before the division, otherwise we're going to have trailing zeroes
entry.getValue().addUploaded((speedInBytesPerSecond * this.threadPauseInterval) / 1000); entry.getValue().addUploaded((speedInBytesPerSecond * this.threadPauseInterval) / 1000);
@ -110,9 +110,7 @@ public class BandwidthDispatcher implements BandwidthDispatcherFacade, Runnable
} }
public void updateTorrentPeers(final InfoHash infoHash, final int seeders, final int leechers) { public void updateTorrentPeers(final InfoHash infoHash, final int seeders, final int leechers) {
if (logger.isDebugEnabled()) { logger.debug("Updating Peers stats for {}", infoHash.humanReadableValue());
logger.debug("Updating Peers stats for {}", infoHash.humanReadableValue());
}
this.lock.writeLock().lock(); this.lock.writeLock().lock();
try { try {
this.weightHolder.addOrUpdate(infoHash, new Peers(seeders, leechers)); this.weightHolder.addOrUpdate(infoHash, new Peers(seeders, leechers));
@ -123,9 +121,7 @@ public class BandwidthDispatcher implements BandwidthDispatcherFacade, Runnable
} }
public void registerTorrent(final InfoHash infoHash) { public void registerTorrent(final InfoHash infoHash) {
if (logger.isDebugEnabled()) { logger.debug("{} has been added to bandwidth dispatcher.", infoHash.humanReadableValue());
logger.debug("{} has been added to bandwidth dispatcher.", infoHash.humanReadableValue());
}
this.lock.writeLock().lock(); this.lock.writeLock().lock();
try { try {
this.torrentsSeedStats.put(infoHash, new TorrentSeedStats()); this.torrentsSeedStats.put(infoHash, new TorrentSeedStats());
@ -136,9 +132,7 @@ public class BandwidthDispatcher implements BandwidthDispatcherFacade, Runnable
} }
public void unregisterTorrent(final InfoHash infoHash) { public void unregisterTorrent(final InfoHash infoHash) {
if (logger.isDebugEnabled()) { logger.debug("{} has been removed from bandwidth dispatcher.", infoHash.humanReadableValue());
logger.debug("{} has been removed from bandwidth dispatcher.", infoHash.humanReadableValue());
}
this.lock.writeLock().lock(); this.lock.writeLock().lock();
try { try {
this.weightHolder.remove(infoHash); this.weightHolder.remove(infoHash);
@ -152,9 +146,7 @@ public class BandwidthDispatcher implements BandwidthDispatcherFacade, Runnable
@VisibleForTesting @VisibleForTesting
void refreshCurrentBandwidth() { void refreshCurrentBandwidth() {
if (logger.isDebugEnabled()) { logger.debug("Refreshing global bandwidth");
logger.debug("Refreshing global bandwidth");
}
this.lock.writeLock().lock(); this.lock.writeLock().lock();
try { try {
this.randomSpeedProvider.refresh(); this.randomSpeedProvider.refresh();
@ -169,25 +161,25 @@ public class BandwidthDispatcher implements BandwidthDispatcherFacade, Runnable
@VisibleForTesting @VisibleForTesting
void recomputeSpeeds() { void recomputeSpeeds() {
if (logger.isDebugEnabled()) { logger.debug("Refreshing all torrents speeds");
logger.debug("Refreshing all torrents speeds");
}
for (final InfoHash infohash : this.torrentsSeedStats.keySet()) { for (final InfoHash infohash : this.torrentsSeedStats.keySet()) {
final double percentOfSpeedAssigned = this.weightHolder.getTotalWeight() == 0.0
? 0.0
: this.weightHolder.getWeightFor(infohash) / this.weightHolder.getTotalWeight();
this.speedMap.compute(infohash, (hash, speed) -> { this.speedMap.compute(infohash, (hash, speed) -> {
if (speed == null) { if (speed == null) {
return new Speed(0); return new Speed(0);
} }
double percentOfSpeedAssigned = this.weightHolder.getTotalWeight() == 0.0
? 0.0
: this.weightHolder.getWeightFor(infohash) / this.weightHolder.getTotalWeight();
speed.setBytesPerSeconds((long) (this.randomSpeedProvider.getInBytesPerSeconds() * percentOfSpeedAssigned)); speed.setBytesPerSeconds((long) (this.randomSpeedProvider.getInBytesPerSeconds() * percentOfSpeedAssigned));
return speed; return speed;
}); });
} }
if (speedChangedListener != null) { if (speedChangedListener != null) {
this.speedChangedListener.speedsHasChanged(Maps.newHashMap(this.speedMap)); this.speedChangedListener.speedsHasChanged(new HashMap<>(this.speedMap));
} }
try { try {
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
final StringBuilder sb = new StringBuilder("All torrents speeds has been refreshed:\n"); final StringBuilder sb = new StringBuilder("All torrents speeds has been refreshed:\n");

View file

@ -3,5 +3,5 @@ package org.araymond.joal.core.bandwith;
import org.araymond.joal.core.torrent.torrent.InfoHash; import org.araymond.joal.core.torrent.torrent.InfoHash;
public interface BandwidthDispatcherFacade { public interface BandwidthDispatcherFacade {
TorrentSeedStats getSeedStatForTorrent(final InfoHash infoHash); TorrentSeedStats getSeedStatForTorrent(InfoHash infoHash);
} }

View file

@ -10,14 +10,13 @@ public class RandomSpeedProvider {
public RandomSpeedProvider(final AppConfiguration appConfiguration) { public RandomSpeedProvider(final AppConfiguration appConfiguration) {
this.appConfiguration = appConfiguration; this.appConfiguration = appConfiguration;
this.refresh(); this.refresh();
} }
public void refresh() { public void refresh() {
final Long minUploadRateInBytes = appConfiguration.getMinUploadRate() * 1000L; final long minUploadRateInBytes = appConfiguration.getMinUploadRate() * 1000L;
final Long maxUploadRateInBytes = appConfiguration.getMaxUploadRate() * 1000L; final long maxUploadRateInBytes = appConfiguration.getMaxUploadRate() * 1000L;
this.currentSpeed = (minUploadRateInBytes.equals(maxUploadRateInBytes)) this.currentSpeed = (minUploadRateInBytes == maxUploadRateInBytes)
? maxUploadRateInBytes ? maxUploadRateInBytes
: ThreadLocalRandom.current().nextLong(minUploadRateInBytes, maxUploadRateInBytes); : ThreadLocalRandom.current().nextLong(minUploadRateInBytes, maxUploadRateInBytes);
} }

View file

@ -5,5 +5,5 @@ import org.araymond.joal.core.torrent.torrent.InfoHash;
import java.util.Map; import java.util.Map;
public interface SpeedChangedListener { public interface SpeedChangedListener {
void speedsHasChanged(final Map<InfoHash, Speed> speeds); void speedsHasChanged(Map<InfoHash, Speed> speeds);
} }

View file

@ -4,15 +4,9 @@ import org.araymond.joal.core.bandwith.Peers;
public class PeersAwareWeightCalculator { public class PeersAwareWeightCalculator {
public double calculate(final Peers peers) { public double calculate(final Peers peers) {
if (peers.getSeeders() == 0) {
return 0.0;
}
final double leechersRatio = peers.getLeechersRatio(); final double leechersRatio = peers.getLeechersRatio();
if (leechersRatio == 0) { return (peers.getSeeders() == 0 || leechersRatio == 0)
return 0.0; ? 0.0
} : leechersRatio * 100 * leechersRatio * peers.getLeechers();
return leechersRatio * 100
* (peers.getSeeders() * leechersRatio)
* (((double) peers.getLeechers()) / peers.getSeeders());
} }
} }

View file

@ -7,6 +7,8 @@ import java.util.Map;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
import static java.util.Optional.ofNullable;
public class WeightHolder<E> { public class WeightHolder<E> {
private final Lock lock; private final Lock lock;
@ -24,13 +26,9 @@ public class WeightHolder<E> {
final double weight = this.weightCalculator.calculate(peers); final double weight = this.weightCalculator.calculate(peers);
lock.lock(); lock.lock();
try { try {
final Weight previousWeight = this.weightMap.put(item, new Weight(weight)); ofNullable(this.weightMap.put(item, new Weight(weight))).ifPresentOrElse(
previousWeight -> this.totalWeight = this.totalWeight - previousWeight.getWeight() + weight,
if (previousWeight != null) { () -> this.totalWeight += weight);
this.totalWeight = this.totalWeight - previousWeight.getWeight() + weight;
} else {
this.totalWeight += weight;
}
} finally { } finally {
lock.unlock(); lock.unlock();
} }
@ -39,28 +37,23 @@ public class WeightHolder<E> {
public void remove(final E item) { public void remove(final E item) {
lock.lock(); lock.lock();
try { try {
final Weight weight = this.weightMap.remove(item); ofNullable(this.weightMap.remove(item))
if (weight != null) { .ifPresent(w -> this.totalWeight -= w.getWeight());
this.totalWeight -= weight.getWeight();
}
} finally { } finally {
lock.unlock(); lock.unlock();
} }
} }
/* /**
* For performance reasons, this method does not benefit from the lock. * For performance reasons, this method does not benefit from the lock.
* That's not a big deal because: * That's not a big deal because:
* - if a value is not yet added it will return 0.0. * - if a value is not yet added it will return 0.0.
* - if a value is still present il will returns the previous value. * - if a value is still present it will return the previous value.
*
*/ */
public double getWeightFor(final E item) { public double getWeightFor(final E item) {
final Weight weight = this.weightMap.get(item); return ofNullable(weightMap.get(item))
if (weight == null) { .map(Weight::getWeight)
return 0.0; .orElse(0.0);
}
return weight.getWeight();
} }
public double getTotalWeight() { public double getTotalWeight() {

View file

@ -22,6 +22,7 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static java.util.Optional.ofNullable;
import static org.araymond.joal.core.client.emulated.BitTorrentClientConfig.HttpHeader; import static org.araymond.joal.core.client.emulated.BitTorrentClientConfig.HttpHeader;
/** /**
@ -55,10 +56,8 @@ public class BitTorrentClient {
@VisibleForTesting @VisibleForTesting
Optional<String> getKey(final InfoHash infoHash, final RequestEvent event) { Optional<String> getKey(final InfoHash infoHash, final RequestEvent event) {
if (keyGenerator == null) { return ofNullable(keyGenerator)
return Optional.empty(); .map(keyGen -> keyGen.getKey(infoHash, event));
}
return Optional.of(keyGenerator.getKey(infoHash, event));
} }
public String getQuery() { public String getQuery() {
@ -83,12 +82,9 @@ public class BitTorrentClient {
.replaceAll("\\{port}", String.valueOf(connectionHandler.getPort())) .replaceAll("\\{port}", String.valueOf(connectionHandler.getPort()))
.replaceAll("\\{numwant}", String.valueOf(this.getNumwant(event))); .replaceAll("\\{numwant}", String.valueOf(this.getNumwant(event)));
final String peerId; final String peerId = this.peerIdGenerator.getShouldUrlEncoded()
if (this.peerIdGenerator.getShouldUrlEncoded()) { ? urlEncoder.encode(this.getPeerId(torrentInfoHash, event))
peerId = urlEncoder.encode(this.getPeerId(torrentInfoHash, event)); : this.getPeerId(torrentInfoHash, event);
} else {
peerId = this.getPeerId(torrentInfoHash, event);
}
emulatedClientQuery = emulatedClientQuery.replaceAll("\\{peerid}", peerId); emulatedClientQuery = emulatedClientQuery.replaceAll("\\{peerid}", peerId);
// set ip or ipv6 then remove placeholders that were left empty // set ip or ipv6 then remove placeholders that were left empty

View file

@ -49,10 +49,8 @@ public class BitTorrentClientConfig {
this.numwant = numwant; this.numwant = numwant;
this.numwantOnStop = numwantOnStop; this.numwantOnStop = numwantOnStop;
if (this.query.contains("{key}")) { if (this.query.contains("{key}") && this.keyGenerator == null) {
if (this.keyGenerator == null) { throw new TorrentClientConfigIntegrityException("Query string contains {key}, but no keyGenerator was found in .client file.");
throw new TorrentClientConfigIntegrityException("Query string contains {key}, but no keyGenerator was found in .client file.");
}
} }
} }

View file

@ -64,14 +64,13 @@ public class BitTorrentClientProvider implements Provider<BitTorrentClient> {
throw new FileNotFoundException(String.format("BitTorrent client configuration file '%s' not found.", clientConfigPath.toAbsolutePath())); throw new FileNotFoundException(String.format("BitTorrent client configuration file '%s' not found.", clientConfigPath.toAbsolutePath()));
} }
final BitTorrentClientConfig config;
try { try {
config = objectMapper.readValue(clientConfigPath.toFile(), BitTorrentClientConfig.class); BitTorrentClientConfig config = objectMapper.readValue(clientConfigPath.toFile(), BitTorrentClientConfig.class);
this.bitTorrentClient = config.createClient();
logger.debug("New client successfully generated.");
} catch (final IOException e) { } catch (final IOException e) {
throw new IllegalStateException(e); throw new IllegalStateException(e);
} }
this.bitTorrentClient = config.createClient();
logger.debug("New client successfully generated.");
} }
static final class SemanticVersionFilenameComparator implements Comparator<String> { static final class SemanticVersionFilenameComparator implements Comparator<String> {

View file

@ -6,7 +6,6 @@ package org.araymond.joal.core.client.emulated;
public class TorrentClientConfigIntegrityException extends RuntimeException { public class TorrentClientConfigIntegrityException extends RuntimeException {
private static final long serialVersionUID = -2441989395992766363L; private static final long serialVersionUID = -2441989395992766363L;
public TorrentClientConfigIntegrityException(final String message) { public TorrentClientConfigIntegrityException(final String message) {
super(message); super(message);
} }

View file

@ -44,7 +44,7 @@ public class UrlEncoder {
*/ */
public String encode(final String toBeEncoded) { public String encode(final String toBeEncoded) {
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
for(final char ch: toBeEncoded.toCharArray()) { for (final char ch : toBeEncoded.toCharArray()) {
sb.append(this.urlEncodeChar(ch)); sb.append(this.urlEncodeChar(ch));
} }
return sb.toString(); return sb.toString();

View file

@ -19,7 +19,6 @@ public class NeverRefreshKeyGenerator extends KeyGenerator {
@JsonProperty(value = "keyCase", required = true) final Casing keyCase @JsonProperty(value = "keyCase", required = true) final Casing keyCase
) { ) {
super(algorithm, keyCase); super(algorithm, keyCase);
this.key = generateKey(); this.key = generateKey();
} }

View file

@ -3,7 +3,6 @@ package org.araymond.joal.core.client.emulated.generator.key;
import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Sets;
import com.turn.ttorrent.common.protocol.TrackerMessage.AnnounceRequestMessage.RequestEvent; import com.turn.ttorrent.common.protocol.TrackerMessage.AnnounceRequestMessage.RequestEvent;
import org.araymond.joal.core.client.emulated.generator.key.algorithm.KeyAlgorithm; import org.araymond.joal.core.client.emulated.generator.key.algorithm.KeyAlgorithm;
import org.araymond.joal.core.client.emulated.utils.Casing; import org.araymond.joal.core.client.emulated.utils.Casing;
@ -11,6 +10,7 @@ import org.araymond.joal.core.torrent.torrent.InfoHash;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit; import java.time.temporal.ChronoUnit;
import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@ -41,7 +41,7 @@ public class TorrentPersistentRefreshKeyGenerator extends KeyGenerator {
} }
private void evictOldEntries() { private void evictOldEntries() {
Sets.newHashSet(this.keyPerTorrent.entrySet()).stream() new HashSet<>(this.keyPerTorrent.entrySet()).stream()
.filter(this::shouldEvictEntry) .filter(this::shouldEvictEntry)
.forEach(entry -> this.keyPerTorrent.remove(entry.getKey())); .forEach(entry -> this.keyPerTorrent.remove(entry.getKey()));
} }

View file

@ -27,5 +27,4 @@ public class NeverRefreshPeerIdGenerator extends PeerIdGenerator {
public String getPeerId(final InfoHash infoHash, final RequestEvent event) { public String getPeerId(final InfoHash infoHash, final RequestEvent event) {
return peerId; return peerId;
} }
} }

View file

@ -3,13 +3,13 @@ package org.araymond.joal.core.client.emulated.generator.peerid;
import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Sets;
import com.turn.ttorrent.common.protocol.TrackerMessage.AnnounceRequestMessage.RequestEvent; import com.turn.ttorrent.common.protocol.TrackerMessage.AnnounceRequestMessage.RequestEvent;
import org.araymond.joal.core.client.emulated.generator.peerid.generation.PeerIdAlgorithm; import org.araymond.joal.core.client.emulated.generator.peerid.generation.PeerIdAlgorithm;
import org.araymond.joal.core.torrent.torrent.InfoHash; import org.araymond.joal.core.torrent.torrent.InfoHash;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit; import java.time.temporal.ChronoUnit;
import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@ -47,7 +47,7 @@ public class TorrentPersistentRefreshPeerIdGenerator extends PeerIdGenerator {
@VisibleForTesting @VisibleForTesting
void evictOldEntries() { void evictOldEntries() {
Sets.newHashSet(this.peerIdPerTorrent.entrySet()).stream() new HashSet<>(this.peerIdPerTorrent.entrySet()).stream()
.filter(this::shouldEvictEntry) .filter(this::shouldEvictEntry)
.forEach(entry -> this.peerIdPerTorrent.remove(entry.getKey())); .forEach(entry -> this.peerIdPerTorrent.remove(entry.getKey()));
} }

View file

@ -27,13 +27,8 @@ public class TorrentVolatileRefreshPeerIdGenerator extends PeerIdGenerator {
@Override @Override
public String getPeerId(final InfoHash infoHash, final RequestEvent event) { public String getPeerId(final InfoHash infoHash, final RequestEvent event) {
final String peerId; this.peerIdPerTorrent.computeIfAbsent(infoHash, k -> super.generatePeerId());
String peerId = this.peerIdPerTorrent.get(infoHash);
if (!this.peerIdPerTorrent.containsKey(infoHash)) {
this.peerIdPerTorrent.put(infoHash, super.generatePeerId());
}
peerId = this.peerIdPerTorrent.get(infoHash);
if (event == RequestEvent.STOPPED) { if (event == RequestEvent.STOPPED) {
this.peerIdPerTorrent.remove(infoHash); this.peerIdPerTorrent.remove(infoHash);

View file

@ -11,5 +11,4 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo;
public interface PeerIdAlgorithm { public interface PeerIdAlgorithm {
String generate(); String generate();
} }

View file

@ -68,7 +68,7 @@ public class RandomPoolWithChecksumPeerIdAlgorithm implements PeerIdAlgorithm {
// Using the current random to generate another random would be completely useless because if the SecureRandom appears to be predictable we will be able to predict the next int as well // Using the current random to generate another random would be completely useless because if the SecureRandom appears to be predictable we will be able to predict the next int as well
int randNumber = new SecureRandom(createSecureRandomSeed()).nextInt(); int randNumber = new SecureRandom(createSecureRandomSeed()).nextInt();
randNumber = Math.abs(randNumber % 40); randNumber = Math.abs(randNumber % 40);
return (randNumber + 10); return randNumber + 10;
} }
@VisibleForTesting @VisibleForTesting

View file

@ -58,27 +58,26 @@ public class AppConfiguration {
} }
private void validate() { private void validate() {
if (java.util.Objects.isNull(minUploadRate)) { if (minUploadRate == null) {
throw new AppConfigurationIntegrityException("minUploadRate must not be null"); throw new AppConfigurationIntegrityException("minUploadRate must not be null");
} } else if (minUploadRate < 0L) {
if (minUploadRate < 0L) {
throw new AppConfigurationIntegrityException("minUploadRate must be at least 0."); throw new AppConfigurationIntegrityException("minUploadRate must be at least 0.");
} }
if (java.util.Objects.isNull(maxUploadRate)) {
if (maxUploadRate == null) {
throw new AppConfigurationIntegrityException("maxUploadRate must not be null"); throw new AppConfigurationIntegrityException("maxUploadRate must not be null");
} } else if (maxUploadRate < 0L) {
if (maxUploadRate < 0L) {
throw new AppConfigurationIntegrityException("maxUploadRate must greater or equal to 0."); throw new AppConfigurationIntegrityException("maxUploadRate must greater or equal to 0.");
} } else if (maxUploadRate < minUploadRate) {
if (maxUploadRate < minUploadRate) {
throw new AppConfigurationIntegrityException("maxUploadRate must be greater or equal to minUploadRate."); throw new AppConfigurationIntegrityException("maxUploadRate must be greater or equal to minUploadRate.");
} }
if (java.util.Objects.isNull(simultaneousSeed)) {
if (simultaneousSeed == null) {
throw new AppConfigurationIntegrityException("simultaneousSeed must not be null"); throw new AppConfigurationIntegrityException("simultaneousSeed must not be null");
} } else if (simultaneousSeed < 1) {
if (simultaneousSeed < 1) {
throw new AppConfigurationIntegrityException("simultaneousSeed must be greater than 0."); throw new AppConfigurationIntegrityException("simultaneousSeed must be greater than 0.");
} }
if (StringUtils.isBlank(client)) { if (StringUtils.isBlank(client)) {
throw new AppConfigurationIntegrityException("client is required, no file name given."); throw new AppConfigurationIntegrityException("client is required, no file name given.");
} }

View file

@ -36,9 +36,7 @@ public class JoalConfigProvider implements Provider<AppConfiguration> {
throw new FileNotFoundException(String.format("App configuration file '%s' not found.", joalConfPath)); throw new FileNotFoundException(String.format("App configuration file '%s' not found.", joalConfPath));
} }
if (logger.isDebugEnabled()) { logger.debug("App configuration file will be searched for in {}", joalConfPath.toAbsolutePath());
logger.debug("App configuration file will be searched for in {}", joalConfPath.toAbsolutePath());
}
} }
public void init() { public void init() {
@ -58,15 +56,14 @@ public class JoalConfigProvider implements Provider<AppConfiguration> {
AppConfiguration loadConfiguration() { AppConfiguration loadConfiguration() {
final AppConfiguration configuration; final AppConfiguration configuration;
try { try {
if (logger.isDebugEnabled()) { logger.debug("Reading json configuration from '{}'.", joalConfPath.toAbsolutePath());
logger.debug("Reading json configuration from '{}'.", joalConfPath.toAbsolutePath());
}
configuration = objectMapper.readValue(joalConfPath.toFile(), AppConfiguration.class); configuration = objectMapper.readValue(joalConfPath.toFile(), AppConfiguration.class);
logger.debug("Successfully red json configuration."); logger.debug("Successfully red json configuration.");
} catch (final IOException e) { } catch (final IOException e) {
logger.error("Failed to read configuration file", e); logger.error("Failed to read configuration file", e);
throw new IllegalStateException(e); throw new IllegalStateException(e);
} }
logger.info("App configuration has been successfully loaded."); logger.info("App configuration has been successfully loaded.");
this.publisher.publishEvent(new ConfigHasBeenLoadedEvent(configuration)); this.publisher.publishEvent(new ConfigHasBeenLoadedEvent(configuration));
return configuration; return configuration;

View file

@ -1,16 +1,16 @@
package org.araymond.joal.core.events.speed; package org.araymond.joal.core.events.speed;
import com.google.common.collect.Maps;
import org.araymond.joal.core.bandwith.Speed; import org.araymond.joal.core.bandwith.Speed;
import org.araymond.joal.core.torrent.torrent.InfoHash; import org.araymond.joal.core.torrent.torrent.InfoHash;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
public class SeedingSpeedsHasChangedEvent { public class SeedingSpeedsHasChangedEvent {
private final Map<InfoHash, Speed> speeds; private final Map<InfoHash, Speed> speeds;
public SeedingSpeedsHasChangedEvent(final Map<InfoHash, Speed> speeds) { public SeedingSpeedsHasChangedEvent(final Map<InfoHash, Speed> speeds) {
this.speeds = Maps.newHashMap(speeds); this.speeds = new HashMap<>(speeds);
} }
public Map<InfoHash, Speed> getSpeeds() { public Map<InfoHash, Speed> getSpeeds() {

View file

@ -4,13 +4,15 @@ import com.google.common.base.Objects;
public class InfoHash { public class InfoHash {
private final String infoHash; private final String infoHash;
private final String humanReadable;
public InfoHash(final byte[] bytes) { public InfoHash(final byte[] bytes) {
this.infoHash = new String(bytes, MockedTorrent.BYTE_ENCODING); this.infoHash = new String(bytes, MockedTorrent.BYTE_ENCODING);
this.humanReadable = infoHash.replaceAll("\\p{C}", "");
} }
public String humanReadableValue() { public String humanReadableValue() {
return infoHash.replaceAll("\\p{C}", ""); return humanReadable;
} }
public String value() { public String value() {

View file

@ -7,8 +7,8 @@ import org.araymond.joal.core.torrent.torrent.MockedTorrent;
*/ */
public interface TorrentFileChangeAware { public interface TorrentFileChangeAware {
void onTorrentFileAdded(final MockedTorrent torrent); void onTorrentFileAdded(MockedTorrent torrent);
void onTorrentFileRemoved(final MockedTorrent torrent); void onTorrentFileRemoved(MockedTorrent torrent);
} }

View file

@ -20,6 +20,8 @@ import java.security.NoSuchAlgorithmException;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static java.util.Optional.ofNullable;
/** /**
* Created by raymo on 28/01/2017. * Created by raymo on 28/01/2017.
*/ */
@ -29,7 +31,6 @@ public class TorrentFileProvider extends FileAlterationListenerAdaptor {
private final TorrentFileWatcher watcher; private final TorrentFileWatcher watcher;
private final Map<File, MockedTorrent> torrentFiles; private final Map<File, MockedTorrent> torrentFiles;
private final Set<TorrentFileChangeAware> torrentFileChangeListener; private final Set<TorrentFileChangeAware> torrentFileChangeListener;
private final Path torrentFolder;
private final Path archiveFolder; private final Path archiveFolder;
@VisibleForTesting @VisibleForTesting
@ -55,7 +56,7 @@ public class TorrentFileProvider extends FileAlterationListenerAdaptor {
} }
public TorrentFileProvider(final SeedManager.JoalFoldersPath joalFoldersPath) throws FileNotFoundException { public TorrentFileProvider(final SeedManager.JoalFoldersPath joalFoldersPath) throws FileNotFoundException {
this.torrentFolder = joalFoldersPath.getTorrentFilesPath(); Path torrentFolder = joalFoldersPath.getTorrentFilesPath();
if (!Files.exists(torrentFolder)) { if (!Files.exists(torrentFolder)) {
logger.error("Folder " + torrentFolder.toAbsolutePath() + " does not exists."); logger.error("Folder " + torrentFolder.toAbsolutePath() + " does not exists.");
throw new FileNotFoundException(String.format("Torrent folder '%s' not found.", torrentFolder.toAbsolutePath())); throw new FileNotFoundException(String.format("Torrent folder '%s' not found.", torrentFolder.toAbsolutePath()));
@ -69,18 +70,11 @@ public class TorrentFileProvider extends FileAlterationListenerAdaptor {
@Override @Override
public void onFileDelete(final File file) { public void onFileDelete(final File file) {
if (!this.torrentFiles.containsKey(file)) { ofNullable(this.torrentFiles.remove(file))
return; .ifPresent(removedTorrent -> {
} logger.info("Torrent file deleting detected, hot deleted file: {}", file.getAbsolutePath());
this.torrentFileChangeListener.forEach(listener -> listener.onTorrentFileRemoved(removedTorrent));
final MockedTorrent torrent = this.torrentFiles.get(file); });
if (torrent == null) {
return;
}
logger.info("Torrent file deleting detected, hot deleted file: {}", file.getAbsolutePath());
this.torrentFiles.remove(file);
this.torrentFileChangeListener.forEach(listener -> listener.onTorrentFileRemoved(torrent));
} }
@Override @Override
@ -144,15 +138,12 @@ public class TorrentFileProvider extends FileAlterationListenerAdaptor {
} }
public void moveToArchiveFolder(final InfoHash infoHash) { public void moveToArchiveFolder(final InfoHash infoHash) {
final Optional<File> first = this.torrentFiles.entrySet().stream() this.torrentFiles.entrySet().stream()
.filter(entry -> entry.getValue().getTorrentInfoHash().equals(infoHash)) .filter(entry -> entry.getValue().getTorrentInfoHash().equals(infoHash))
.map(Map.Entry::getKey) .map(Map.Entry::getKey)
.findFirst(); .findAny()
if (first.isPresent()) { .ifPresentOrElse(this::moveToArchiveFolder,
this.moveToArchiveFolder(first.get()); () -> logger.warn("Cannot move torrent {} to archive folder. Torrent file seems not to be registered in TorrentFileProvider.", infoHash));
} else {
logger.warn("Cannot move torrent {} to archive folder. Torrent file seems not to be registered in TorrentFileProvider.", infoHash);
}
} }
public int getTorrentCount() { public int getTorrentCount() {

View file

@ -17,20 +17,16 @@ import org.araymond.joal.core.ttorrent.client.announcer.AnnouncerFacade;
import org.araymond.joal.core.ttorrent.client.announcer.AnnouncerFactory; import org.araymond.joal.core.ttorrent.client.announcer.AnnouncerFactory;
import org.araymond.joal.core.ttorrent.client.announcer.request.AnnounceRequest; import org.araymond.joal.core.ttorrent.client.announcer.request.AnnounceRequest;
import org.araymond.joal.core.ttorrent.client.announcer.request.AnnouncerExecutor; import org.araymond.joal.core.ttorrent.client.announcer.request.AnnouncerExecutor;
import org.slf4j.Logger;
import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisher;
import java.time.temporal.ChronoUnit; import java.time.temporal.ChronoUnit;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.stream.Collectors;
import static org.slf4j.LoggerFactory.getLogger; import static java.util.stream.Collectors.toList;
public class Client implements TorrentFileChangeAware, ClientFacade { public class Client implements TorrentFileChangeAware, ClientFacade {
private static final Logger logger = getLogger(Client.class);
private final AppConfiguration appConfiguration; private final AppConfiguration appConfiguration;
private final TorrentFileProvider torrentFileProvider; private final TorrentFileProvider torrentFileProvider;
private final ApplicationEventPublisher eventPublisher; private final ApplicationEventPublisher eventPublisher;
@ -85,10 +81,10 @@ public class Client implements TorrentFileChangeAware, ClientFacade {
} }
} }
}); });
for (int i = 0; i < this.appConfiguration.getSimultaneousSeed(); i++) { for (int i = 0; i < this.appConfiguration.getSimultaneousSeed(); i++) {
try { try {
this.lock.writeLock().lock(); this.lock.writeLock().lock();
this.addTorrent(); this.addTorrent();
} catch (final NoMoreTorrentsFileAvailableException ignored) { } catch (final NoMoreTorrentsFileAvailableException ignored) {
break; break;
@ -107,7 +103,7 @@ public class Client implements TorrentFileChangeAware, ClientFacade {
final MockedTorrent torrent = this.torrentFileProvider.getTorrentNotIn( final MockedTorrent torrent = this.torrentFileProvider.getTorrentNotIn(
this.currentlySeedingAnnouncer.stream() this.currentlySeedingAnnouncer.stream()
.map(Announcer::getTorrentInfoHash) .map(Announcer::getTorrentInfoHash)
.collect(Collectors.toList()) .collect(toList())
); );
final Announcer announcer = this.announcerFactory.create(torrent); final Announcer announcer = this.announcerFactory.create(torrent);
this.currentlySeedingAnnouncer.add(announcer); this.currentlySeedingAnnouncer.add(announcer);

View file

@ -78,7 +78,7 @@ public class ConnectionHandler {
urlConnection.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36"); urlConnection.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36");
try (final BufferedReader in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), Charsets.UTF_8))) { try (final BufferedReader in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), Charsets.UTF_8))) {
return InetAddress.getByName(in.readLine()); return InetAddress.getByName(in.readLine());
}finally { } finally {
// Ensure all streams associated with http connection are closed // Ensure all streams associated with http connection are closed
final InputStream err = ((HttpURLConnection) urlConnection).getErrorStream(); final InputStream err = ((HttpURLConnection) urlConnection).getErrorStream();
try { if (err != null) err.close(); } try { if (err != null) err.close(); }
@ -126,7 +126,6 @@ public class ConnectionHandler {
for (int port = ConnectionHandler.PORT_RANGE_START; port <= ConnectionHandler.PORT_RANGE_END; port++) { for (int port = ConnectionHandler.PORT_RANGE_START; port <= ConnectionHandler.PORT_RANGE_END; port++) {
final InetSocketAddress tryAddress = new InetSocketAddress(port); final InetSocketAddress tryAddress = new InetSocketAddress(port);
try { try {
channel = ServerSocketChannel.open(); channel = ServerSocketChannel.open();
channel.socket().bind(tryAddress); channel.socket().bind(tryAddress);

View file

@ -89,7 +89,6 @@ public class DelayQueue<T extends DelayQueue.InfoHashAble> {
return item; return item;
} }
@SuppressWarnings("NullableProblems")
@Override @Override
public int compareTo(final IntervalAware o) { public int compareTo(final IntervalAware o) {
return this.releaseAt.compareTo(o.releaseAt); return this.releaseAt.compareTo(o.releaseAt);

View file

@ -42,7 +42,7 @@ public class Announcer implements AnnouncerFacade {
} }
private TrackerClient buildTrackerClient(final MockedTorrent torrent, HttpClient httpClient) { private TrackerClient buildTrackerClient(final MockedTorrent torrent, HttpClient httpClient) {
final List<URI> trackerURIs = torrent.getAnnounceList().stream() // Use a list to keep it ordered final List<URI> trackerURIs = torrent.getAnnounceList().stream() // Use a list to keep it ordered
.sequential() .sequential()
.flatMap(Collection::stream) .flatMap(Collection::stream)
.collect(Collectors.toList()); .collect(Collectors.toList());

View file

@ -1,6 +1,5 @@
package org.araymond.joal.core.ttorrent.client.announcer.request; package org.araymond.joal.core.ttorrent.client.announcer.request;
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.ThreadFactoryBuilder; import com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.araymond.joal.core.torrent.torrent.InfoHash; import org.araymond.joal.core.torrent.torrent.InfoHash;
import org.araymond.joal.core.ttorrent.client.announcer.Announcer; import org.araymond.joal.core.ttorrent.client.announcer.Announcer;
@ -72,7 +71,7 @@ public class AnnouncerExecutor {
} }
public List<Announcer> denyAll() { public List<Announcer> denyAll() {
final Set<InfoHash> infoHashes = Sets.newHashSet(this.currentlyRunning.keySet()); final Set<InfoHash> infoHashes = new HashSet<>(this.currentlyRunning.keySet());
final List<Announcer> announcersCanceled = new ArrayList<>(); final List<Announcer> announcersCanceled = new ArrayList<>();
for (final InfoHash infoHash: infoHashes) { for (final InfoHash infoHash: infoHashes) {

View file

@ -23,65 +23,49 @@ public class AnnounceEventPublisher implements AnnounceResponseHandlerChainEleme
@Override @Override
public void onAnnouncerWillAnnounce(final Announcer announcer, final RequestEvent event) { public void onAnnouncerWillAnnounce(final Announcer announcer, final RequestEvent event) {
if(logger.isDebugEnabled()) { logger.debug("Publish WillAnnounceEvent event for {}.", announcer.getTorrentInfoHash().humanReadableValue());
logger.debug("Publish WillAnnounceEvent event for {}.", announcer.getTorrentInfoHash().humanReadableValue());
}
this.eventPublisher.publishEvent(new WillAnnounceEvent(announcer, event)); this.eventPublisher.publishEvent(new WillAnnounceEvent(announcer, event));
} }
@Override @Override
public void onAnnounceStartSuccess(final Announcer announcer, final SuccessAnnounceResponse result) { public void onAnnounceStartSuccess(final Announcer announcer, final SuccessAnnounceResponse result) {
if(logger.isDebugEnabled()) { logger.debug("Publish SuccessfullyAnnounceEvent event for {}.", announcer.getTorrentInfoHash().humanReadableValue());
logger.debug("Publish SuccessfullyAnnounceEvent event for {}.", announcer.getTorrentInfoHash().humanReadableValue());
}
this.eventPublisher.publishEvent(new SuccessfullyAnnounceEvent(announcer, RequestEvent.STARTED)); this.eventPublisher.publishEvent(new SuccessfullyAnnounceEvent(announcer, RequestEvent.STARTED));
} }
@Override @Override
public void onAnnounceStartFails(final Announcer announcer, final Throwable throwable) { public void onAnnounceStartFails(final Announcer announcer, final Throwable throwable) {
if(logger.isDebugEnabled()) { logger.debug("Publish FailedToAnnounceEvent event for {}.", announcer.getTorrentInfoHash().humanReadableValue());
logger.debug("Publish FailedToAnnounceEvent event for {}.", announcer.getTorrentInfoHash().humanReadableValue());
}
this.eventPublisher.publishEvent(new FailedToAnnounceEvent(announcer, RequestEvent.STARTED, throwable.getMessage())); this.eventPublisher.publishEvent(new FailedToAnnounceEvent(announcer, RequestEvent.STARTED, throwable.getMessage()));
} }
@Override @Override
public void onAnnounceRegularSuccess(final Announcer announcer, final SuccessAnnounceResponse result) { public void onAnnounceRegularSuccess(final Announcer announcer, final SuccessAnnounceResponse result) {
if(logger.isDebugEnabled()) { logger.debug("Publish SuccessfullyAnnounceEvent event for {}.", announcer.getTorrentInfoHash().humanReadableValue());
logger.debug("Publish SuccessfullyAnnounceEvent event for {}.", announcer.getTorrentInfoHash().humanReadableValue());
}
this.eventPublisher.publishEvent(new SuccessfullyAnnounceEvent(announcer, RequestEvent.NONE)); this.eventPublisher.publishEvent(new SuccessfullyAnnounceEvent(announcer, RequestEvent.NONE));
} }
@Override @Override
public void onAnnounceRegularFails(final Announcer announcer, final Throwable throwable) { public void onAnnounceRegularFails(final Announcer announcer, final Throwable throwable) {
if(logger.isDebugEnabled()) { logger.debug("Publish FailedToAnnounceEvent event for {}.", announcer.getTorrentInfoHash().humanReadableValue());
logger.debug("Publish FailedToAnnounceEvent event for {}.", announcer.getTorrentInfoHash().humanReadableValue());
}
this.eventPublisher.publishEvent(new FailedToAnnounceEvent(announcer, RequestEvent.NONE, throwable.getMessage())); this.eventPublisher.publishEvent(new FailedToAnnounceEvent(announcer, RequestEvent.NONE, throwable.getMessage()));
} }
@Override @Override
public void onAnnounceStopSuccess(final Announcer announcer, final SuccessAnnounceResponse result) { public void onAnnounceStopSuccess(final Announcer announcer, final SuccessAnnounceResponse result) {
if(logger.isDebugEnabled()) { logger.debug("Publish SuccessfullyAnnounceEvent event for {}.", announcer.getTorrentInfoHash().humanReadableValue());
logger.debug("Publish SuccessfullyAnnounceEvent event for {}.", announcer.getTorrentInfoHash().humanReadableValue());
}
this.eventPublisher.publishEvent(new SuccessfullyAnnounceEvent(announcer, RequestEvent.STOPPED)); this.eventPublisher.publishEvent(new SuccessfullyAnnounceEvent(announcer, RequestEvent.STOPPED));
} }
@Override @Override
public void onAnnounceStopFails(final Announcer announcer, final Throwable throwable) { public void onAnnounceStopFails(final Announcer announcer, final Throwable throwable) {
if(logger.isDebugEnabled()) { logger.debug("Publish FailedToAnnounceEvent event for {}.", announcer.getTorrentInfoHash().humanReadableValue());
logger.debug("Publish FailedToAnnounceEvent event for {}.", announcer.getTorrentInfoHash().humanReadableValue());
}
this.eventPublisher.publishEvent(new FailedToAnnounceEvent(announcer, RequestEvent.STOPPED, throwable.getMessage())); this.eventPublisher.publishEvent(new FailedToAnnounceEvent(announcer, RequestEvent.STOPPED, throwable.getMessage()));
} }
@Override @Override
public void onTooManyAnnounceFailedInARaw(final Announcer announcer, final TooMuchAnnouncesFailedInARawException e) { public void onTooManyAnnounceFailedInARaw(final Announcer announcer, final TooMuchAnnouncesFailedInARawException e) {
if(logger.isDebugEnabled()) { logger.debug("Publish TooManyAnnouncesFailedEvent event for {}.", announcer.getTorrentInfoHash().humanReadableValue());
logger.debug("Publish TooManyAnnouncesFailedEvent event for {}.", announcer.getTorrentInfoHash().humanReadableValue());
}
this.eventPublisher.publishEvent(new TooManyAnnouncesFailedEvent(announcer)); this.eventPublisher.publishEvent(new TooManyAnnouncesFailedEvent(announcer));
} }

View file

@ -27,33 +27,25 @@ public class AnnounceReEnqueuer implements AnnounceResponseHandlerChainElement {
@Override @Override
public void onAnnounceStartSuccess(final Announcer announcer, final SuccessAnnounceResponse result) { public void onAnnounceStartSuccess(final Announcer announcer, final SuccessAnnounceResponse result) {
if (logger.isDebugEnabled()) { logger.debug("Enqueue torrent {} in regular queue.", announcer.getTorrentInfoHash().humanReadableValue());
logger.debug("Enqueue torrent {} in regular queue.", announcer.getTorrentInfoHash().humanReadableValue());
}
this.delayQueue.addOrReplace(AnnounceRequest.createRegular(announcer), result.getInterval(), ChronoUnit.SECONDS); this.delayQueue.addOrReplace(AnnounceRequest.createRegular(announcer), result.getInterval(), ChronoUnit.SECONDS);
} }
@Override @Override
public void onAnnounceStartFails(final Announcer announcer, final Throwable throwable) { public void onAnnounceStartFails(final Announcer announcer, final Throwable throwable) {
if (logger.isDebugEnabled()) { logger.debug("Enqueue torrent {} in start queue once again (because it failed).", announcer.getTorrentInfoHash().humanReadableValue());
logger.debug("Enqueue torrent {} in start queue once again (because it failed).", announcer.getTorrentInfoHash().humanReadableValue());
}
this.delayQueue.addOrReplace(AnnounceRequest.createStart(announcer), announcer.getLastKnownInterval(), ChronoUnit.SECONDS); this.delayQueue.addOrReplace(AnnounceRequest.createStart(announcer), announcer.getLastKnownInterval(), ChronoUnit.SECONDS);
} }
@Override @Override
public void onAnnounceRegularSuccess(final Announcer announcer, final SuccessAnnounceResponse result) { public void onAnnounceRegularSuccess(final Announcer announcer, final SuccessAnnounceResponse result) {
if (logger.isDebugEnabled()) { logger.debug("Enqueue torrent {} in regular queue.", announcer.getTorrentInfoHash().humanReadableValue());
logger.debug("Enqueue torrent {} in regular queue.", announcer.getTorrentInfoHash().humanReadableValue());
}
this.delayQueue.addOrReplace(AnnounceRequest.createRegular(announcer), result.getInterval(), ChronoUnit.SECONDS); this.delayQueue.addOrReplace(AnnounceRequest.createRegular(announcer), result.getInterval(), ChronoUnit.SECONDS);
} }
@Override @Override
public void onAnnounceRegularFails(final Announcer announcer, final Throwable throwable) { public void onAnnounceRegularFails(final Announcer announcer, final Throwable throwable) {
if (logger.isDebugEnabled()) { logger.debug("Enqueue torrent {} in regular queue once again (because it failed).", announcer.getTorrentInfoHash().humanReadableValue());
logger.debug("Enqueue torrent {} in regular queue once again (because it failed).", announcer.getTorrentInfoHash().humanReadableValue());
}
this.delayQueue.addOrReplace(AnnounceRequest.createRegular(announcer), announcer.getLastKnownInterval(), ChronoUnit.SECONDS); this.delayQueue.addOrReplace(AnnounceRequest.createRegular(announcer), announcer.getLastKnownInterval(), ChronoUnit.SECONDS);
} }
@ -63,9 +55,7 @@ public class AnnounceReEnqueuer implements AnnounceResponseHandlerChainElement {
@Override @Override
public void onAnnounceStopFails(final Announcer announcer, final Throwable throwable) { public void onAnnounceStopFails(final Announcer announcer, final Throwable throwable) {
if (logger.isDebugEnabled()) { logger.debug("Enqueue torrent {} in stop queue once again (because it failed).", announcer.getTorrentInfoHash().humanReadableValue());
logger.debug("Enqueue torrent {} in stop queue once again (because it failed).", announcer.getTorrentInfoHash().humanReadableValue());
}
this.delayQueue.addOrReplace(AnnounceRequest.createStop(announcer), 0, ChronoUnit.SECONDS); this.delayQueue.addOrReplace(AnnounceRequest.createStop(announcer), 0, ChronoUnit.SECONDS);
} }

View file

@ -6,8 +6,8 @@ import org.araymond.joal.core.ttorrent.client.announcer.exceptions.TooMuchAnnoun
import org.araymond.joal.core.ttorrent.client.announcer.request.SuccessAnnounceResponse; import org.araymond.joal.core.ttorrent.client.announcer.request.SuccessAnnounceResponse;
public interface AnnounceResponseCallback { public interface AnnounceResponseCallback {
void onAnnounceWillAnnounce(final RequestEvent event, final Announcer announcer); void onAnnounceWillAnnounce(RequestEvent event, Announcer announcer);
void onAnnounceSuccess(final RequestEvent event, final Announcer announcer, final SuccessAnnounceResponse result); void onAnnounceSuccess(RequestEvent event, Announcer announcer, SuccessAnnounceResponse result);
void onAnnounceFailure(final RequestEvent event, final Announcer announcer, final Throwable throwable); void onAnnounceFailure(RequestEvent event, Announcer announcer, Throwable throwable);
void onTooManyAnnounceFailedInARaw(final RequestEvent event, final Announcer announcer, final TooMuchAnnouncesFailedInARawException e); void onTooManyAnnounceFailedInARaw(RequestEvent event, Announcer announcer, TooMuchAnnouncesFailedInARawException e);
} }

View file

@ -6,12 +6,12 @@ import org.araymond.joal.core.ttorrent.client.announcer.exceptions.TooMuchAnnoun
import org.araymond.joal.core.ttorrent.client.announcer.request.SuccessAnnounceResponse; import org.araymond.joal.core.ttorrent.client.announcer.request.SuccessAnnounceResponse;
public interface AnnounceResponseHandlerChainElement { public interface AnnounceResponseHandlerChainElement {
void onAnnouncerWillAnnounce(final Announcer announcer, RequestEvent event); void onAnnouncerWillAnnounce(Announcer announcer, RequestEvent event);
void onAnnounceStartSuccess(final Announcer announcer, final SuccessAnnounceResponse result); void onAnnounceStartSuccess(Announcer announcer, SuccessAnnounceResponse result);
void onAnnounceStartFails(final Announcer announcer, final Throwable throwable); void onAnnounceStartFails(Announcer announcer, Throwable throwable);
void onAnnounceRegularSuccess(final Announcer announcer, final SuccessAnnounceResponse result); void onAnnounceRegularSuccess(Announcer announcer, SuccessAnnounceResponse result);
void onAnnounceRegularFails(final Announcer announcer, final Throwable throwable); void onAnnounceRegularFails(Announcer announcer, Throwable throwable);
void onAnnounceStopSuccess(final Announcer announcer, final SuccessAnnounceResponse result); void onAnnounceStopSuccess(Announcer announcer, SuccessAnnounceResponse result);
void onAnnounceStopFails(final Announcer announcer, final Throwable throwable); void onAnnounceStopFails(Announcer announcer, Throwable throwable);
void onTooManyAnnounceFailedInARaw(final Announcer announcer, final TooMuchAnnouncesFailedInARawException e); void onTooManyAnnounceFailedInARaw(Announcer announcer, TooMuchAnnouncesFailedInARawException e);
} }

View file

@ -24,9 +24,7 @@ public class BandwidthDispatcherNotifier implements AnnounceResponseHandlerChain
@Override @Override
public void onAnnounceStartSuccess(final Announcer announcer, final SuccessAnnounceResponse result) { public void onAnnounceStartSuccess(final Announcer announcer, final SuccessAnnounceResponse result) {
if(logger.isDebugEnabled()) { logger.debug("Register {} in bandwidth dispatcher and update stats.", announcer.getTorrentInfoHash().humanReadableValue());
logger.debug("Register {} in bandwidth dispatcher and update stats.", announcer.getTorrentInfoHash().humanReadableValue());
}
final InfoHash infoHash = announcer.getTorrentInfoHash(); final InfoHash infoHash = announcer.getTorrentInfoHash();
this.bandwidthDispatcher.registerTorrent(infoHash); this.bandwidthDispatcher.registerTorrent(infoHash);
this.bandwidthDispatcher.updateTorrentPeers(infoHash, result.getSeeders(), result.getLeechers()); this.bandwidthDispatcher.updateTorrentPeers(infoHash, result.getSeeders(), result.getLeechers());
@ -38,9 +36,7 @@ public class BandwidthDispatcherNotifier implements AnnounceResponseHandlerChain
@Override @Override
public void onAnnounceRegularSuccess(final Announcer announcer, final SuccessAnnounceResponse result) { public void onAnnounceRegularSuccess(final Announcer announcer, final SuccessAnnounceResponse result) {
if(logger.isDebugEnabled()) { logger.debug("Update {} stats in bandwidth dispatcher.", announcer.getTorrentInfoHash().humanReadableValue());
logger.debug("Update {} stats in bandwidth dispatcher.", announcer.getTorrentInfoHash().humanReadableValue());
}
final InfoHash infoHash = announcer.getTorrentInfoHash(); final InfoHash infoHash = announcer.getTorrentInfoHash();
this.bandwidthDispatcher.updateTorrentPeers(infoHash, result.getSeeders(), result.getLeechers()); this.bandwidthDispatcher.updateTorrentPeers(infoHash, result.getSeeders(), result.getLeechers());
} }
@ -51,9 +47,7 @@ public class BandwidthDispatcherNotifier implements AnnounceResponseHandlerChain
@Override @Override
public void onAnnounceStopSuccess(final Announcer announcer, final SuccessAnnounceResponse result) { public void onAnnounceStopSuccess(final Announcer announcer, final SuccessAnnounceResponse result) {
if(logger.isDebugEnabled()) { logger.debug("Unregister {} from bandwidth dispatcher.", announcer.getTorrentInfoHash().humanReadableValue());
logger.debug("Unregister {} from bandwidth dispatcher.", announcer.getTorrentInfoHash().humanReadableValue());
}
this.bandwidthDispatcher.unregisterTorrent(announcer.getTorrentInfoHash()); this.bandwidthDispatcher.unregisterTorrent(announcer.getTorrentInfoHash());
} }
@ -63,9 +57,7 @@ public class BandwidthDispatcherNotifier implements AnnounceResponseHandlerChain
@Override @Override
public void onTooManyAnnounceFailedInARaw(final Announcer announcer, final TooMuchAnnouncesFailedInARawException e) { public void onTooManyAnnounceFailedInARaw(final Announcer announcer, final TooMuchAnnouncesFailedInARawException e) {
if(logger.isDebugEnabled()) { logger.debug("Unregister {} from bandwidth dispatcher.", announcer.getTorrentInfoHash().humanReadableValue());
logger.debug("Unregister {} from bandwidth dispatcher.", announcer.getTorrentInfoHash().humanReadableValue());
}
this.bandwidthDispatcher.unregisterTorrent(announcer.getTorrentInfoHash()); this.bandwidthDispatcher.unregisterTorrent(announcer.getTorrentInfoHash());
} }
} }

View file

@ -45,9 +45,7 @@ public class ClientNotifier implements AnnounceResponseHandlerChainElement {
@Override @Override
public void onAnnounceStopSuccess(final Announcer announcer, final SuccessAnnounceResponse result) { public void onAnnounceStopSuccess(final Announcer announcer, final SuccessAnnounceResponse result) {
if(logger.isDebugEnabled()) { logger.debug("Notify client that a torrent has stopped.");
logger.debug("Notify client that a torrent has stopped.");
}
this.client.onTorrentHasStopped(announcer); this.client.onTorrentHasStopped(announcer);
} }
@ -57,9 +55,7 @@ public class ClientNotifier implements AnnounceResponseHandlerChainElement {
@Override @Override
public void onTooManyAnnounceFailedInARaw(final Announcer announcer, final TooMuchAnnouncesFailedInARawException e) { public void onTooManyAnnounceFailedInARaw(final Announcer announcer, final TooMuchAnnouncesFailedInARawException e) {
if(logger.isDebugEnabled()) { logger.debug("Notify client that a torrent has failed too many times.");
logger.debug("Notify client that a torrent has failed too many times.");
}
this.client.onTooManyFailedInARaw(announcer); this.client.onTooManyFailedInARaw(announcer);
} }
} }

View file

@ -73,8 +73,7 @@ public class TrackerClient {
final AnnounceResponseMessage announceResponseMessage = (AnnounceResponseMessage) responseMessage; final AnnounceResponseMessage announceResponseMessage = (AnnounceResponseMessage) responseMessage;
final int interval = announceResponseMessage.getInterval(); final int interval = announceResponseMessage.getInterval();
// Subtract one to seeders since we are one of them. final int seeders = announceResponseMessage.getComplete() == 0 ? 0 : announceResponseMessage.getComplete() - 1; // Subtract one to seeders since we are one of them
final int seeders = announceResponseMessage.getComplete() == 0 ? 0 : announceResponseMessage.getComplete() - 1;
final int leechers = announceResponseMessage.getIncomplete(); final int leechers = announceResponseMessage.getIncomplete();
return new SuccessAnnounceResponse(interval, seeders, leechers); return new SuccessAnnounceResponse(interval, seeders, leechers);
} }

View file

@ -1,7 +1,6 @@
package org.araymond.joal.core.ttorrent.client.announcer.tracker; package org.araymond.joal.core.ttorrent.client.announcer.tracker;
import com.google.common.collect.Iterators; import com.google.common.collect.Iterators;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.net.URI; import java.net.URI;
@ -9,8 +8,6 @@ import java.util.Iterator;
import java.util.List; import java.util.List;
public class TrackerClientUriProvider { public class TrackerClientUriProvider {
private static final Logger logger = LoggerFactory.getLogger(TrackerClientUriProvider.class);
private final Iterator<URI> addressIterator; private final Iterator<URI> addressIterator;
private URI currentURI = null; private URI currentURI = null;

View file

@ -26,7 +26,7 @@ public class TrackerResponseHandler implements ResponseHandler<TrackerMessage> {
} }
final int contentLength = entity.getContentLength() < 1 ? 1024 : (int) entity.getContentLength(); final int contentLength = entity.getContentLength() < 1 ? 1024 : (int) entity.getContentLength();
try(final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(contentLength)) { try (final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(contentLength)) {
if (response.getStatusLine().getStatusCode() >= 300) { if (response.getStatusLine().getStatusCode() >= 300) {
logger.warn("Tracker response is an error."); logger.warn("Tracker response is an error.");
} }

View file

@ -37,7 +37,7 @@ public class JacksonConfig {
/** /**
* Forces the timezone to be added to every LocalDateTime * Forces the timezone to be added to every LocalDateTime
*/ */
public static final class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> { public static final class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {
@Override @Override
public void serialize(final LocalDateTime value, final JsonGenerator gen, final SerializerProvider serializers) throws IOException { public void serialize(final LocalDateTime value, final JsonGenerator gen, final SerializerProvider serializers) throws IOException {
final ZonedDateTime zonedDateTime = value.atZone(ZoneId.systemDefault()); final ZonedDateTime zonedDateTime = value.atZone(ZoneId.systemDefault());

View file

@ -1,13 +1,9 @@
package org.araymond.joal.web.config; package org.araymond.joal.web.config;
import org.araymond.joal.web.annotations.ConditionalOnWebUi; import org.araymond.joal.web.annotations.ConditionalOnWebUi;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered; import org.springframework.core.Ordered;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.*;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@ConditionalOnWebUi @ConditionalOnWebUi
// Do not use @EnableWebMvc as it will remove all the default springboot config. // Do not use @EnableWebMvc as it will remove all the default springboot config.

View file

@ -20,9 +20,9 @@ public class JoalMessageSendingTemplate {
this.messageSendingOperations = messageSendingOperations; this.messageSendingOperations = messageSendingOperations;
} }
public void convertAndSend(final String s, final MessagePayload payload) throws MessagingException { public void convertAndSend(final String destination, final MessagePayload payload) throws MessagingException {
final StompMessage stompMessage = StompMessage.wrap(payload); final StompMessage stompMessage = StompMessage.wrap(payload);
messageSendingOperations.convertAndSend(s, stompMessage); messageSendingOperations.convertAndSend(destination, stompMessage);
} }
} }

View file

@ -1,10 +1,10 @@
package org.araymond.joal.core.events.speed; package org.araymond.joal.core.events.speed;
import com.google.common.collect.Maps;
import org.araymond.joal.core.bandwith.Speed; import org.araymond.joal.core.bandwith.Speed;
import org.araymond.joal.core.torrent.torrent.InfoHash; import org.araymond.joal.core.torrent.torrent.InfoHash;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@ -13,7 +13,7 @@ public class SeedingSpeedsHasChangedEventTest {
@Test @Test
public void shouldBuild() { public void shouldBuild() {
final Map<InfoHash, Speed> speeds = Maps.newHashMap(); final Map<InfoHash, Speed> speeds = new HashMap<>();
final SeedingSpeedsHasChangedEvent event = new SeedingSpeedsHasChangedEvent(speeds); final SeedingSpeedsHasChangedEvent event = new SeedingSpeedsHasChangedEvent(speeds);
assertThat(event.getSpeeds()).isEqualTo(speeds); assertThat(event.getSpeeds()).isEqualTo(speeds);