PeerDiscovery: Change getPeers() return type from array to list.

This gets rid of a lot of array/list conversions.
This commit is contained in:
Andreas Schildbach 2020-03-04 12:21:29 +01:00
parent a165fb1834
commit 06bd0a841e
10 changed files with 50 additions and 47 deletions

View file

@ -930,7 +930,7 @@ public class PeerGroup implements TransactionBroadcaster {
final Stopwatch watch = Stopwatch.createStarted(); final Stopwatch watch = Stopwatch.createStarted();
final List<PeerAddress> addressList = new LinkedList<>(); final List<PeerAddress> addressList = new LinkedList<>();
for (PeerDiscovery peerDiscovery : peerDiscoverers /* COW */) { for (PeerDiscovery peerDiscovery : peerDiscoverers /* COW */) {
InetSocketAddress[] addresses; List<InetSocketAddress> addresses;
try { try {
addresses = peerDiscovery.getPeers(requiredServices, peerDiscoveryTimeoutMillis, TimeUnit.MILLISECONDS); addresses = peerDiscovery.getPeers(requiredServices, peerDiscoveryTimeoutMillis, TimeUnit.MILLISECONDS);
} catch (PeerDiscoveryException e) { } catch (PeerDiscoveryException e) {

View file

@ -84,14 +84,14 @@ public class DnsDiscovery extends MultiplexingDiscovery {
} }
@Override @Override
public InetSocketAddress[] getPeers(long services, long timeoutValue, TimeUnit timeoutUnit) throws PeerDiscoveryException { public List<InetSocketAddress> getPeers(long services, long timeoutValue, TimeUnit timeoutUnit) throws PeerDiscoveryException {
if (services != 0) if (services != 0)
throw new PeerDiscoveryException("DNS seeds cannot filter by services: " + services); throw new PeerDiscoveryException("DNS seeds cannot filter by services: " + services);
try { try {
InetAddress[] response = InetAddress.getAllByName(hostname); InetAddress[] response = InetAddress.getAllByName(hostname);
InetSocketAddress[] result = new InetSocketAddress[response.length]; List<InetSocketAddress> result = new ArrayList<>(response.length);
for (int i = 0; i < response.length; i++) for (InetAddress r : response)
result[i] = new InetSocketAddress(response[i], params.getPort()); result.add(new InetSocketAddress(r, params.getPort()));
return result; return result;
} catch (UnknownHostException e) { } catch (UnknownHostException e) {
throw new PeerDiscoveryException(e); throw new PeerDiscoveryException(e);

View file

@ -84,7 +84,7 @@ public class HttpDiscovery implements PeerDiscovery {
} }
@Override @Override
public InetSocketAddress[] getPeers(long services, long timeoutValue, TimeUnit timeoutUnit) throws PeerDiscoveryException { public List<InetSocketAddress> getPeers(long services, long timeoutValue, TimeUnit timeoutUnit) throws PeerDiscoveryException {
try { try {
HttpUrl.Builder url = HttpUrl.get(details.uri).newBuilder(); HttpUrl.Builder url = HttpUrl.get(details.uri).newBuilder();
if (services != 0) if (services != 0)
@ -114,7 +114,7 @@ public class HttpDiscovery implements PeerDiscovery {
} }
@VisibleForTesting @VisibleForTesting
public InetSocketAddress[] protoToAddrs(PeerSeedProtos.SignedPeerSeeds proto) throws PeerDiscoveryException, public List<InetSocketAddress> protoToAddrs(PeerSeedProtos.SignedPeerSeeds proto) throws PeerDiscoveryException,
InvalidProtocolBufferException, SignatureDecodeException, SignatureException { InvalidProtocolBufferException, SignatureDecodeException, SignatureException {
if (details.pubkey != null) { if (details.pubkey != null) {
if (!Arrays.equals(proto.getPubkey().toByteArray(), details.pubkey.getPubKey())) if (!Arrays.equals(proto.getPubkey().toByteArray(), details.pubkey.getPubKey()))
@ -127,10 +127,9 @@ public class HttpDiscovery implements PeerDiscovery {
throw new PeerDiscoveryException("Seed data is more than one day old: replay attack?"); throw new PeerDiscoveryException("Seed data is more than one day old: replay attack?");
if (!seeds.getNet().equals(params.getPaymentProtocolId())) if (!seeds.getNet().equals(params.getPaymentProtocolId()))
throw new PeerDiscoveryException("Network mismatch"); throw new PeerDiscoveryException("Network mismatch");
InetSocketAddress[] results = new InetSocketAddress[seeds.getSeedCount()]; List<InetSocketAddress> results = new ArrayList<>(seeds.getSeedCount());
int i = 0;
for (PeerSeedProtos.PeerSeedData data : seeds.getSeedList()) for (PeerSeedProtos.PeerSeedData data : seeds.getSeedList())
results[i++] = new InetSocketAddress(data.getIpAddress(), data.getPort()); results.add(new InetSocketAddress(data.getIpAddress(), data.getPort()));
return results; return results;
} }

View file

@ -26,7 +26,6 @@ import org.slf4j.LoggerFactory;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
@ -104,46 +103,46 @@ public class MultiplexingDiscovery implements PeerDiscovery {
} }
@Override @Override
public InetSocketAddress[] getPeers(final long services, final long timeoutValue, final TimeUnit timeoutUnit) throws PeerDiscoveryException { public List<InetSocketAddress> getPeers(final long services, final long timeoutValue, final TimeUnit timeoutUnit) throws PeerDiscoveryException {
vThreadPool = createExecutor(); vThreadPool = createExecutor();
try { try {
List<Callable<InetSocketAddress[]>> tasks = new ArrayList<>(); List<Callable<List<InetSocketAddress>>> tasks = new ArrayList<>();
if (parallelQueries) { if (parallelQueries) {
for (final PeerDiscovery seed : seeds) { for (final PeerDiscovery seed : seeds) {
tasks.add(new Callable<InetSocketAddress[]>() { tasks.add(new Callable<List<InetSocketAddress>>() {
@Override @Override
public InetSocketAddress[] call() throws Exception { public List<InetSocketAddress> call() throws Exception {
return seed.getPeers(services, timeoutValue, timeoutUnit); return seed.getPeers(services, timeoutValue, timeoutUnit);
} }
}); });
} }
} else { } else {
tasks.add(new Callable<InetSocketAddress[]>() { tasks.add(new Callable<List<InetSocketAddress>>() {
@Override @Override
public InetSocketAddress[] call() throws Exception { public List<InetSocketAddress> call() throws Exception {
List<InetSocketAddress> peers = new LinkedList<>(); List<InetSocketAddress> peers = new LinkedList<>();
for (final PeerDiscovery seed : seeds) for (final PeerDiscovery seed : seeds)
peers.addAll(Arrays.asList(seed.getPeers(services, timeoutValue, timeoutUnit))); peers.addAll(seed.getPeers(services, timeoutValue, timeoutUnit));
return peers.toArray(new InetSocketAddress[peers.size()]); return peers;
} }
}); });
} }
final List<Future<InetSocketAddress[]>> futures = vThreadPool.invokeAll(tasks, timeoutValue, timeoutUnit); final List<Future<List<InetSocketAddress>>> futures = vThreadPool.invokeAll(tasks, timeoutValue, timeoutUnit);
ArrayList<InetSocketAddress> addrs = new ArrayList<>(); List<InetSocketAddress> addrs = new ArrayList<>();
for (int i = 0; i < futures.size(); i++) { for (int i = 0; i < futures.size(); i++) {
Future<InetSocketAddress[]> future = futures.get(i); Future<List<InetSocketAddress>> future = futures.get(i);
if (future.isCancelled()) { if (future.isCancelled()) {
log.warn("Seed {}: timed out", parallelQueries ? seeds.get(i) : "any"); log.warn("Seed {}: timed out", parallelQueries ? seeds.get(i) : "any");
continue; // Timed out. continue; // Timed out.
} }
final InetSocketAddress[] inetAddresses; final List<InetSocketAddress> inetAddresses;
try { try {
inetAddresses = future.get(); inetAddresses = future.get();
} catch (ExecutionException e) { } catch (ExecutionException e) {
log.warn("Seed {}: failed to look up: {}", parallelQueries ? seeds.get(i) : "any", e.getMessage()); log.warn("Seed {}: failed to look up: {}", parallelQueries ? seeds.get(i) : "any", e.getMessage());
continue; continue;
} }
Collections.addAll(addrs, inetAddresses); addrs.addAll(inetAddresses);
} }
if (addrs.size() == 0) if (addrs.size() == 0)
throw new PeerDiscoveryException("No peer discovery returned any results in " throw new PeerDiscoveryException("No peer discovery returned any results in "
@ -151,7 +150,7 @@ public class MultiplexingDiscovery implements PeerDiscovery {
if (shufflePeers) if (shufflePeers)
Collections.shuffle(addrs); Collections.shuffle(addrs);
vThreadPool.shutdownNow(); vThreadPool.shutdownNow();
return addrs.toArray(new InetSocketAddress[addrs.size()]); return addrs;
} catch (InterruptedException e) { } catch (InterruptedException e) {
throw new PeerDiscoveryException(e); throw new PeerDiscoveryException(e);
} finally { } finally {

View file

@ -18,6 +18,7 @@
package org.bitcoinj.net.discovery; package org.bitcoinj.net.discovery;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.bitcoinj.core.VersionMessage; import org.bitcoinj.core.VersionMessage;
@ -30,10 +31,10 @@ public interface PeerDiscovery {
// TODO: Flesh out this interface a lot more. // TODO: Flesh out this interface a lot more.
/** /**
* Returns an array of addresses. This method may block. * Queries the addresses. This method may block.
* @param services Required services as a bitmask, e.g. {@link VersionMessage#NODE_NETWORK}. * @param services Required services as a bitmask, e.g. {@link VersionMessage#NODE_NETWORK}.
*/ */
InetSocketAddress[] getPeers(long services, long timeoutValue, TimeUnit timeoutUnit) throws PeerDiscoveryException; List<InetSocketAddress> getPeers(long services, long timeoutValue, TimeUnit timeoutUnit) throws PeerDiscoveryException;
/** Stops any discovery in progress when we want to shut down quickly. */ /** Stops any discovery in progress when we want to shut down quickly. */
void shutdown(); void shutdown();

View file

@ -23,6 +23,8 @@ import javax.annotation.Nullable;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
/** /**
@ -82,10 +84,10 @@ public class SeedPeers implements PeerDiscovery {
} }
/** /**
* Returns an array containing all the Bitcoin nodes within the list. * Returns all the Bitcoin nodes within the list.
*/ */
@Override @Override
public InetSocketAddress[] getPeers(long services, long timeoutValue, TimeUnit timeoutUnit) throws PeerDiscoveryException { public List<InetSocketAddress> getPeers(long services, long timeoutValue, TimeUnit timeoutUnit) throws PeerDiscoveryException {
if (services != 0) if (services != 0)
throw new PeerDiscoveryException("Pre-determined peers cannot be filtered by services: " + services); throw new PeerDiscoveryException("Pre-determined peers cannot be filtered by services: " + services);
try { try {
@ -95,10 +97,10 @@ public class SeedPeers implements PeerDiscovery {
} }
} }
private InetSocketAddress[] allPeers() throws UnknownHostException { private List<InetSocketAddress> allPeers() throws UnknownHostException {
InetSocketAddress[] addresses = new InetSocketAddress[seedAddrs.length]; List<InetSocketAddress> addresses = new ArrayList<>(seedAddrs.length);
for (int i = 0; i < seedAddrs.length; ++i) { for (int seedAddr : seedAddrs) {
addresses[i] = new InetSocketAddress(convertAddress(seedAddrs[i]), params.getPort()); addresses.add(new InetSocketAddress(convertAddress(seedAddr), params.getPort()));
} }
return addresses; return addresses;
} }

View file

@ -141,14 +141,14 @@ public class PeerGroupTest extends TestWithPeerGroup {
final AtomicBoolean result = new AtomicBoolean(); final AtomicBoolean result = new AtomicBoolean();
peerGroup.addPeerDiscovery(new PeerDiscovery() { peerGroup.addPeerDiscovery(new PeerDiscovery() {
@Override @Override
public InetSocketAddress[] getPeers(long services, long unused, TimeUnit unused2) throws PeerDiscoveryException { public List<InetSocketAddress> getPeers(long services, long unused, TimeUnit unused2) throws PeerDiscoveryException {
if (!result.getAndSet(true)) { if (!result.getAndSet(true)) {
// Pretend we are not connected to the internet. // Pretend we are not connected to the internet.
throw new PeerDiscoveryException("test failure"); throw new PeerDiscoveryException("test failure");
} else { } else {
// Return a bogus address. // Return a bogus address.
latch.countDown(); latch.countDown();
return new InetSocketAddress[]{new InetSocketAddress("localhost", 1)}; return Arrays.asList(new InetSocketAddress("localhost", 1));
} }
} }
@ -165,13 +165,13 @@ public class PeerGroupTest extends TestWithPeerGroup {
// Utility method to create a PeerDiscovery with a certain number of addresses. // Utility method to create a PeerDiscovery with a certain number of addresses.
private PeerDiscovery createPeerDiscovery(int nrOfAddressesWanted, int port) { private PeerDiscovery createPeerDiscovery(int nrOfAddressesWanted, int port) {
final InetSocketAddress[] addresses = new InetSocketAddress[nrOfAddressesWanted]; final List<InetSocketAddress> addresses = new ArrayList<>(nrOfAddressesWanted);
for (int addressNr = 0; addressNr < nrOfAddressesWanted; addressNr++) { for (int addressNr = 0; addressNr < nrOfAddressesWanted; addressNr++) {
// make each address unique by using the counter to increment the port. // make each address unique by using the counter to increment the port.
addresses[addressNr] = new InetSocketAddress("localhost", port + addressNr); addresses.add(new InetSocketAddress("localhost", port + addressNr));
} }
return new PeerDiscovery() { return new PeerDiscovery() {
public InetSocketAddress[] getPeers(long services, long unused, TimeUnit unused2) throws PeerDiscoveryException { public List<InetSocketAddress> getPeers(long services, long unused, TimeUnit unused2) throws PeerDiscoveryException {
return addresses; return addresses;
} }
public void shutdown() { public void shutdown() {
@ -557,8 +557,8 @@ public class PeerGroupTest extends TestWithPeerGroup {
peerGroup.addPreMessageReceivedEventListener(preMessageReceivedListener); peerGroup.addPreMessageReceivedEventListener(preMessageReceivedListener);
peerGroup.addPeerDiscovery(new PeerDiscovery() { peerGroup.addPeerDiscovery(new PeerDiscovery() {
@Override @Override
public InetSocketAddress[] getPeers(long services, long unused, TimeUnit unused2) throws PeerDiscoveryException { public List<InetSocketAddress> getPeers(long services, long unused, TimeUnit unused2) throws PeerDiscoveryException {
return addresses.toArray(new InetSocketAddress[addresses.size()]); return addresses;
} }
@Override @Override

View file

@ -20,6 +20,7 @@ import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.bitcoinj.params.MainNetParams; import org.bitcoinj.params.MainNetParams;
@ -33,7 +34,7 @@ public class DnsDiscoveryTest {
DnsDiscovery dnsDiscovery = new DnsDiscovery(seeds, MainNetParams.get()); DnsDiscovery dnsDiscovery = new DnsDiscovery(seeds, MainNetParams.get());
assertTrue(dnsDiscovery.seeds.size() == 2); assertTrue(dnsDiscovery.seeds.size() == 2);
for (PeerDiscovery peerDiscovery : dnsDiscovery.seeds) { for (PeerDiscovery peerDiscovery : dnsDiscovery.seeds) {
assertTrue(peerDiscovery.getPeers(0, 100, TimeUnit.MILLISECONDS).length > 0); assertTrue(peerDiscovery.getPeers(0, 100, TimeUnit.MILLISECONDS).size() > 0);
} }
} }
@ -47,8 +48,8 @@ public class DnsDiscoveryTest {
public void testGetPeersReturnsNotEmptyListOfSocketAddresses() throws PeerDiscoveryException { public void testGetPeersReturnsNotEmptyListOfSocketAddresses() throws PeerDiscoveryException {
DnsDiscovery.DnsSeedDiscovery dnsSeedDiscovery = new DnsDiscovery.DnsSeedDiscovery(MainNetParams.get(), DnsDiscovery.DnsSeedDiscovery dnsSeedDiscovery = new DnsDiscovery.DnsSeedDiscovery(MainNetParams.get(),
"localhost"); "localhost");
InetSocketAddress[] inetSocketAddresses = dnsSeedDiscovery.getPeers(0, 100, TimeUnit.MILLISECONDS); List<InetSocketAddress> inetSocketAddresses = dnsSeedDiscovery.getPeers(0, 100, TimeUnit.MILLISECONDS);
assertNotEquals(0, inetSocketAddresses.length); assertNotEquals(0, inetSocketAddresses.size());
} }
@Test(expected = PeerDiscoveryException.class) @Test(expected = PeerDiscoveryException.class)

View file

@ -22,6 +22,7 @@ import org.bitcoinj.params.MainNetParams;
import org.junit.Test; import org.junit.Test;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.equalTo;
@ -49,7 +50,7 @@ public class SeedPeersTest {
@Test @Test
public void getPeers_length() throws Exception{ public void getPeers_length() throws Exception{
SeedPeers seedPeers = new SeedPeers(MAINNET); SeedPeers seedPeers = new SeedPeers(MAINNET);
InetSocketAddress[] addresses = seedPeers.getPeers(0, 0, TimeUnit.SECONDS); List<InetSocketAddress> addresses = seedPeers.getPeers(0, 0, TimeUnit.SECONDS);
assertThat(addresses.length, equalTo(MAINNET.getAddrSeeds().length)); assertThat(addresses.size(), equalTo(MAINNET.getAddrSeeds().length));
} }
} }

View file

@ -41,14 +41,14 @@ import java.util.concurrent.TimeUnit;
* Prints a list of IP addresses obtained from DNS. * Prints a list of IP addresses obtained from DNS.
*/ */
public class PrintPeers { public class PrintPeers {
private static InetSocketAddress[] dnsPeers; private static List<InetSocketAddress> dnsPeers;
private static void printElapsed(long start) { private static void printElapsed(long start) {
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
System.out.println(String.format("Took %.2f seconds", (now - start) / 1000.0)); System.out.println(String.format("Took %.2f seconds", (now - start) / 1000.0));
} }
private static void printPeers(InetSocketAddress[] addresses) { private static void printPeers(List<InetSocketAddress> addresses) {
for (InetSocketAddress address : addresses) { for (InetSocketAddress address : addresses) {
String hostAddress = address.getAddress().getHostAddress(); String hostAddress = address.getAddress().getHostAddress();
System.out.println(String.format("%s:%d", hostAddress, address.getPort())); System.out.println(String.format("%s:%d", hostAddress, address.getPort()));