implement synchronized Tracker structure
This commit is contained in:
parent
534f827afc
commit
7f75a1ac77
4 changed files with 124 additions and 2 deletions
|
|
@ -31,7 +31,7 @@ public class Torrent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T extends Collection<Peer>> void updatePeers(T src) {
|
public <T extends Collection<Peer>> void putPeers(T src) {
|
||||||
for (Peer peer : src) {
|
for (Peer peer : src) {
|
||||||
peers.put(peer);
|
peers.put(peer);
|
||||||
}
|
}
|
||||||
48
src/main/java/com/mykola2312/retracker/tracker/Tracker.java
Normal file
48
src/main/java/com/mykola2312/retracker/tracker/Tracker.java
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
package com.mykola2312.retracker.tracker;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/* Tracker meant to be called from multiple running threads,
|
||||||
|
* so thread-safety ensured by synchronized methods.
|
||||||
|
*/
|
||||||
|
public class Tracker {
|
||||||
|
private HashMap<InfoHash, Torrent> torrents = new HashMap<InfoHash, Torrent>();
|
||||||
|
|
||||||
|
/* Adds peer to torrent's PeerSet. If no such Torrent present,
|
||||||
|
* creates the Torrent.
|
||||||
|
*/
|
||||||
|
public synchronized void announcePeer(InfoHash infoHash, Peer peer) {
|
||||||
|
Torrent torrent = torrents.get(infoHash);
|
||||||
|
if (torrent != null) {
|
||||||
|
torrent.putPeers(List.of(peer));
|
||||||
|
} else {
|
||||||
|
// create torrent and initiate PeerSet with first announced peer
|
||||||
|
torrent = new Torrent(infoHash, peer);
|
||||||
|
torrents.put(torrent.getInfoHash(), torrent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Adds multiple peers to torrent. If no such Torrent present,
|
||||||
|
* creates the torrent.
|
||||||
|
*/
|
||||||
|
public synchronized <T extends Collection<Peer>> void announcePeers(InfoHash infoHash, T src) {
|
||||||
|
Torrent torrent = torrents.get(infoHash);
|
||||||
|
if (torrent != null) {
|
||||||
|
torrent.putPeers(src);
|
||||||
|
} else {
|
||||||
|
torrent = new Torrent(infoHash);
|
||||||
|
torrent.putPeers(src);
|
||||||
|
torrents.put(torrent.getInfoHash(), torrent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get list of peers at this very moment.
|
||||||
|
public synchronized <T extends Collection<Peer>> void getPeers(InfoHash infoHash, T dst) {
|
||||||
|
Torrent torrent = torrents.get(infoHash);
|
||||||
|
if (torrent != null) {
|
||||||
|
torrent.copyPeers(dst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -31,7 +31,7 @@ public class TorrentTest {
|
||||||
|
|
||||||
List<Peer> src = Arrays.asList(new Peer(newAddress("127.0.0.1", 1337)),
|
List<Peer> src = Arrays.asList(new Peer(newAddress("127.0.0.1", 1337)),
|
||||||
new Peer(newAddress("127.0.0.1", 1338)));
|
new Peer(newAddress("127.0.0.1", 1338)));
|
||||||
torrent.updatePeers(src);
|
torrent.putPeers(src);
|
||||||
{
|
{
|
||||||
ArrayList<Peer> copy = new ArrayList<Peer>();
|
ArrayList<Peer> copy = new ArrayList<Peer>();
|
||||||
torrent.copyPeers(copy);
|
torrent.copyPeers(copy);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
package com.mykola2312.retracker.tracker;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
public class TrackerTest {
|
||||||
|
private static InetSocketAddress newAddress(String addr, int port) throws UnknownHostException {
|
||||||
|
return new InetSocketAddress(InetAddress.getByName(addr), port);
|
||||||
|
}
|
||||||
|
|
||||||
|
class TrackerJob implements Runnable {
|
||||||
|
private Tracker tracker;
|
||||||
|
private InfoHash infoHash;
|
||||||
|
private Peer peer;
|
||||||
|
|
||||||
|
public TrackerJob(Tracker tracker, InfoHash infoHash, Peer peer) {
|
||||||
|
this.tracker = tracker;
|
||||||
|
this.infoHash = infoHash;
|
||||||
|
this.peer = peer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
tracker.announcePeer(infoHash, peer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTrackerPutAndGet() throws Exception {
|
||||||
|
final InfoHash infoHash = new InfoHash();
|
||||||
|
infoHash.fromString("360775c6629eb06e60d90201aed1b7bc49a1ce16");
|
||||||
|
|
||||||
|
Tracker tracker = new Tracker();
|
||||||
|
|
||||||
|
ArrayList<Thread> threads = new ArrayList<Thread>();
|
||||||
|
for (int i = 0; i < 32; i++) {
|
||||||
|
TrackerJob job = new TrackerJob(tracker, infoHash,
|
||||||
|
new Peer(newAddress("127.0.0.1", 1337 + i)));
|
||||||
|
Thread thread = new Thread(job);
|
||||||
|
thread.start();
|
||||||
|
threads.add(thread);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// wait for all threads to finish
|
||||||
|
for (Thread thread : threads) {
|
||||||
|
thread.join();
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayList<Peer> peers = new ArrayList<Peer>(32);
|
||||||
|
tracker.getPeers(infoHash, peers);
|
||||||
|
|
||||||
|
assertEquals(32, peers.size());
|
||||||
|
|
||||||
|
// check if every port present
|
||||||
|
for (int i = 0; i < 32; i++) {
|
||||||
|
int port = 1337 + i;
|
||||||
|
boolean peerPortPresent = false;
|
||||||
|
for (Peer peer : peers) {
|
||||||
|
if (peer.getAddress().getPort() == port) {
|
||||||
|
peerPortPresent = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(true, peerPortPresent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue