Replace infinite Iterable/Iterator with dedicated types
Related: #4065 Motivation: DnsNameResolver was using a special Iterable/Iterator implementation that yields an infinite stream of DNS server addresses. However, this seems to cause confusion. Modifications: - Make DnsServerAddresses an abstract class with an abstract stream() method that returns DnsServerAddressStream - Add DnsServerAddressStream that yields DNS server address infinitely - Remove DnsServerResolver(Group) constructors that accept only a single server address, which wasn't very useful in practice - Extract the DnsServerAddresses implementations to top level - DnsServerAddresses.defaultAddresses() now returns DnsServerAddresses. - Add DnsServerAddresses.defaultAddressList() instead Result: Less confusion and more explicitness
This commit is contained in:
parent
48ee962d08
commit
99f701fd59
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2015 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package io.netty.resolver.dns;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
abstract class DefaultDnsServerAddresses extends DnsServerAddresses {
|
||||
|
||||
protected final InetSocketAddress[] addresses;
|
||||
private final String strVal;
|
||||
|
||||
DefaultDnsServerAddresses(String type, InetSocketAddress[] addresses) {
|
||||
this.addresses = addresses;
|
||||
|
||||
final StringBuilder buf = new StringBuilder(type.length() + 2 + addresses.length * 16);
|
||||
buf.append(type).append('(');
|
||||
|
||||
for (InetSocketAddress a: addresses) {
|
||||
buf.append(a).append(", ");
|
||||
}
|
||||
|
||||
buf.setLength(buf.length() - 2);
|
||||
buf.append(')');
|
||||
|
||||
strVal = buf.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return strVal;
|
||||
}
|
||||
}
|
@ -41,7 +41,6 @@ import io.netty.util.collection.IntObjectHashMap;
|
||||
import io.netty.util.concurrent.FastThreadLocal;
|
||||
import io.netty.util.concurrent.Future;
|
||||
import io.netty.util.concurrent.Promise;
|
||||
import io.netty.util.internal.InternalThreadLocalMap;
|
||||
import io.netty.util.internal.OneTimeTask;
|
||||
import io.netty.util.internal.PlatformDependent;
|
||||
import io.netty.util.internal.SystemPropertyUtil;
|
||||
@ -91,7 +90,7 @@ public class DnsNameResolver extends SimpleNameResolver<InetSocketAddress> {
|
||||
private static final DatagramDnsResponseDecoder DECODER = new DatagramDnsResponseDecoder();
|
||||
private static final DatagramDnsQueryEncoder ENCODER = new DatagramDnsQueryEncoder();
|
||||
|
||||
final Iterable<InetSocketAddress> nameServerAddresses;
|
||||
final DnsServerAddresses nameServerAddresses;
|
||||
final ChannelFuture bindFuture;
|
||||
final DatagramChannel ch;
|
||||
|
||||
@ -107,11 +106,11 @@ public class DnsNameResolver extends SimpleNameResolver<InetSocketAddress> {
|
||||
*/
|
||||
final ConcurrentMap<String, List<DnsCacheEntry>> resolveCache = PlatformDependent.newConcurrentHashMap();
|
||||
|
||||
private final FastThreadLocal<Iterator<InetSocketAddress>> nameServerAddrIterator =
|
||||
new FastThreadLocal<Iterator<InetSocketAddress>>() {
|
||||
private final FastThreadLocal<DnsServerAddressStream> nameServerAddrStream =
|
||||
new FastThreadLocal<DnsServerAddressStream>() {
|
||||
@Override
|
||||
protected Iterator<InetSocketAddress> initialValue() throws Exception {
|
||||
return nameServerAddresses.iterator();
|
||||
protected DnsServerAddressStream initialValue() throws Exception {
|
||||
return nameServerAddresses.stream();
|
||||
}
|
||||
};
|
||||
|
||||
@ -131,72 +130,18 @@ public class DnsNameResolver extends SimpleNameResolver<InetSocketAddress> {
|
||||
|
||||
private volatile int maxPayloadSize;
|
||||
|
||||
/**
|
||||
* Creates a new DNS-based name resolver that communicates with a single DNS server.
|
||||
*
|
||||
* @param eventLoop the {@link EventLoop} which will perform the communication with the DNS servers
|
||||
* @param channelType the type of the {@link DatagramChannel} to create
|
||||
* @param nameServerAddress the address of the DNS server
|
||||
*/
|
||||
public DnsNameResolver(
|
||||
EventLoop eventLoop, Class<? extends DatagramChannel> channelType,
|
||||
InetSocketAddress nameServerAddress) {
|
||||
this(eventLoop, channelType, ANY_LOCAL_ADDR, nameServerAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new DNS-based name resolver that communicates with a single DNS server.
|
||||
*
|
||||
* @param eventLoop the {@link EventLoop} which will perform the communication with the DNS servers
|
||||
* @param channelType the type of the {@link DatagramChannel} to create
|
||||
* @param localAddress the local address of the {@link DatagramChannel}
|
||||
* @param nameServerAddress the address of the DNS server
|
||||
*/
|
||||
public DnsNameResolver(
|
||||
EventLoop eventLoop, Class<? extends DatagramChannel> channelType,
|
||||
InetSocketAddress localAddress, InetSocketAddress nameServerAddress) {
|
||||
this(eventLoop, new ReflectiveChannelFactory<DatagramChannel>(channelType), localAddress, nameServerAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new DNS-based name resolver that communicates with a single DNS server.
|
||||
*
|
||||
* @param eventLoop the {@link EventLoop} which will perform the communication with the DNS servers
|
||||
* @param channelFactory the {@link ChannelFactory} that will create a {@link DatagramChannel}
|
||||
* @param nameServerAddress the address of the DNS server
|
||||
*/
|
||||
public DnsNameResolver(
|
||||
EventLoop eventLoop, ChannelFactory<? extends DatagramChannel> channelFactory,
|
||||
InetSocketAddress nameServerAddress) {
|
||||
this(eventLoop, channelFactory, ANY_LOCAL_ADDR, nameServerAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new DNS-based name resolver that communicates with a single DNS server.
|
||||
*
|
||||
* @param eventLoop the {@link EventLoop} which will perform the communication with the DNS servers
|
||||
* @param channelFactory the {@link ChannelFactory} that will create a {@link DatagramChannel}
|
||||
* @param localAddress the local address of the {@link DatagramChannel}
|
||||
* @param nameServerAddress the address of the DNS server
|
||||
*/
|
||||
public DnsNameResolver(
|
||||
EventLoop eventLoop, ChannelFactory<? extends DatagramChannel> channelFactory,
|
||||
InetSocketAddress localAddress, InetSocketAddress nameServerAddress) {
|
||||
this(eventLoop, channelFactory, localAddress, DnsServerAddresses.singleton(nameServerAddress));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new DNS-based name resolver that communicates with the specified list of DNS servers.
|
||||
*
|
||||
* @param eventLoop the {@link EventLoop} which will perform the communication with the DNS servers
|
||||
* @param channelType the type of the {@link DatagramChannel} to create
|
||||
* @param nameServerAddresses the addresses of the DNS server. For each DNS query, a new {@link Iterator} is
|
||||
* created from this {@link Iterable} to determine which DNS server should be contacted
|
||||
* for the next retry in case of failure.
|
||||
* @param nameServerAddresses the addresses of the DNS server. For each DNS query, a new stream is created from
|
||||
* this to determine which DNS server should be contacted for the next retry in case
|
||||
* of failure.
|
||||
*/
|
||||
public DnsNameResolver(
|
||||
EventLoop eventLoop, Class<? extends DatagramChannel> channelType,
|
||||
Iterable<InetSocketAddress> nameServerAddresses) {
|
||||
DnsServerAddresses nameServerAddresses) {
|
||||
this(eventLoop, channelType, ANY_LOCAL_ADDR, nameServerAddresses);
|
||||
}
|
||||
|
||||
@ -206,13 +151,13 @@ public class DnsNameResolver extends SimpleNameResolver<InetSocketAddress> {
|
||||
* @param eventLoop the {@link EventLoop} which will perform the communication with the DNS servers
|
||||
* @param channelType the type of the {@link DatagramChannel} to create
|
||||
* @param localAddress the local address of the {@link DatagramChannel}
|
||||
* @param nameServerAddresses the addresses of the DNS server. For each DNS query, a new {@link Iterator} is
|
||||
* created from this {@link Iterable} to determine which DNS server should be contacted
|
||||
* for the next retry in case of failure.
|
||||
* @param nameServerAddresses the addresses of the DNS server. For each DNS query, a new stream is created from
|
||||
* this to determine which DNS server should be contacted for the next retry in case
|
||||
* of failure.
|
||||
*/
|
||||
public DnsNameResolver(
|
||||
EventLoop eventLoop, Class<? extends DatagramChannel> channelType,
|
||||
InetSocketAddress localAddress, Iterable<InetSocketAddress> nameServerAddresses) {
|
||||
InetSocketAddress localAddress, DnsServerAddresses nameServerAddresses) {
|
||||
this(eventLoop, new ReflectiveChannelFactory<DatagramChannel>(channelType), localAddress, nameServerAddresses);
|
||||
}
|
||||
|
||||
@ -221,13 +166,13 @@ public class DnsNameResolver extends SimpleNameResolver<InetSocketAddress> {
|
||||
*
|
||||
* @param eventLoop the {@link EventLoop} which will perform the communication with the DNS servers
|
||||
* @param channelFactory the {@link ChannelFactory} that will create a {@link DatagramChannel}
|
||||
* @param nameServerAddresses the addresses of the DNS server. For each DNS query, a new {@link Iterator} is
|
||||
* created from this {@link Iterable} to determine which DNS server should be contacted
|
||||
* for the next retry in case of failure.
|
||||
* @param nameServerAddresses the addresses of the DNS server. For each DNS query, a new stream is created from
|
||||
* this to determine which DNS server should be contacted for the next retry in case
|
||||
* of failure.
|
||||
*/
|
||||
public DnsNameResolver(
|
||||
EventLoop eventLoop, ChannelFactory<? extends DatagramChannel> channelFactory,
|
||||
Iterable<InetSocketAddress> nameServerAddresses) {
|
||||
DnsServerAddresses nameServerAddresses) {
|
||||
this(eventLoop, channelFactory, ANY_LOCAL_ADDR, nameServerAddresses);
|
||||
}
|
||||
|
||||
@ -237,13 +182,13 @@ public class DnsNameResolver extends SimpleNameResolver<InetSocketAddress> {
|
||||
* @param eventLoop the {@link EventLoop} which will perform the communication with the DNS servers
|
||||
* @param channelFactory the {@link ChannelFactory} that will create a {@link DatagramChannel}
|
||||
* @param localAddress the local address of the {@link DatagramChannel}
|
||||
* @param nameServerAddresses the addresses of the DNS server. For each DNS query, a new {@link Iterator} is
|
||||
* created from this {@link Iterable} to determine which DNS server should be contacted
|
||||
* for the next retry in case of failure.
|
||||
* @param nameServerAddresses the addresses of the DNS server. For each DNS query, a new stream is created from
|
||||
* this to determine which DNS server should be contacted for the next retry in case
|
||||
* of failure.
|
||||
*/
|
||||
public DnsNameResolver(
|
||||
EventLoop eventLoop, ChannelFactory<? extends DatagramChannel> channelFactory,
|
||||
InetSocketAddress localAddress, Iterable<InetSocketAddress> nameServerAddresses) {
|
||||
InetSocketAddress localAddress, DnsServerAddresses nameServerAddresses) {
|
||||
|
||||
super(eventLoop);
|
||||
|
||||
@ -251,10 +196,6 @@ public class DnsNameResolver extends SimpleNameResolver<InetSocketAddress> {
|
||||
checkNotNull(nameServerAddresses, "nameServerAddresses");
|
||||
checkNotNull(localAddress, "localAddress");
|
||||
|
||||
if (!nameServerAddresses.iterator().hasNext()) {
|
||||
throw new IllegalArgumentException("nameServerAddresses is empty");
|
||||
}
|
||||
|
||||
this.nameServerAddresses = nameServerAddresses;
|
||||
bindFuture = newChannel(channelFactory, localAddress);
|
||||
ch = (DatagramChannel) bindFuture.channel();
|
||||
@ -922,17 +863,7 @@ public class DnsNameResolver extends SimpleNameResolver<InetSocketAddress> {
|
||||
}
|
||||
|
||||
private InetSocketAddress nextNameServerAddress() {
|
||||
final InternalThreadLocalMap tlm = InternalThreadLocalMap.get();
|
||||
Iterator<InetSocketAddress> i = nameServerAddrIterator.get(tlm);
|
||||
if (i.hasNext()) {
|
||||
return i.next();
|
||||
}
|
||||
|
||||
// The iterator has reached at its end, create a new iterator.
|
||||
// We should not reach here if a user created nameServerAddresses via DnsServerAddresses, but just in case ..
|
||||
i = nameServerAddresses.iterator();
|
||||
nameServerAddrIterator.set(tlm, i);
|
||||
return i.next();
|
||||
return nameServerAddrStream.get().next();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -67,7 +67,7 @@ abstract class DnsNameResolverContext<T> {
|
||||
};
|
||||
|
||||
private final DnsNameResolver parent;
|
||||
private final Iterator<InetSocketAddress> nameServerAddrs;
|
||||
private final DnsServerAddressStream nameServerAddrs;
|
||||
private final Promise<T> promise;
|
||||
private final String hostname;
|
||||
private final boolean traceEnabled;
|
||||
@ -88,7 +88,7 @@ abstract class DnsNameResolverContext<T> {
|
||||
this.promise = promise;
|
||||
this.hostname = hostname;
|
||||
|
||||
nameServerAddrs = parent.nameServerAddresses.iterator();
|
||||
nameServerAddrs = parent.nameServerAddresses.stream();
|
||||
maxAllowedQueries = parent.maxQueriesPerResolve();
|
||||
resolveAddressTypes = parent.resolveAddressTypesUnsafe();
|
||||
traceEnabled = parent.isTraceEnabled();
|
||||
|
@ -36,53 +36,27 @@ public final class DnsNameResolverGroup extends NameResolverGroup<InetSocketAddr
|
||||
|
||||
private final ChannelFactory<? extends DatagramChannel> channelFactory;
|
||||
private final InetSocketAddress localAddress;
|
||||
private final Iterable<InetSocketAddress> nameServerAddresses;
|
||||
private final DnsServerAddresses nameServerAddresses;
|
||||
|
||||
public DnsNameResolverGroup(
|
||||
Class<? extends DatagramChannel> channelType,
|
||||
InetSocketAddress nameServerAddress) {
|
||||
this(channelType, ANY_LOCAL_ADDR, nameServerAddress);
|
||||
}
|
||||
|
||||
public DnsNameResolverGroup(
|
||||
Class<? extends DatagramChannel> channelType,
|
||||
InetSocketAddress localAddress, InetSocketAddress nameServerAddress) {
|
||||
this(new ReflectiveChannelFactory<DatagramChannel>(channelType), localAddress, nameServerAddress);
|
||||
}
|
||||
|
||||
public DnsNameResolverGroup(
|
||||
ChannelFactory<? extends DatagramChannel> channelFactory,
|
||||
InetSocketAddress nameServerAddress) {
|
||||
this(channelFactory, ANY_LOCAL_ADDR, nameServerAddress);
|
||||
}
|
||||
|
||||
public DnsNameResolverGroup(
|
||||
ChannelFactory<? extends DatagramChannel> channelFactory,
|
||||
InetSocketAddress localAddress, InetSocketAddress nameServerAddress) {
|
||||
this(channelFactory, localAddress, DnsServerAddresses.singleton(nameServerAddress));
|
||||
}
|
||||
|
||||
public DnsNameResolverGroup(
|
||||
Class<? extends DatagramChannel> channelType,
|
||||
Iterable<InetSocketAddress> nameServerAddresses) {
|
||||
Class<? extends DatagramChannel> channelType, DnsServerAddresses nameServerAddresses) {
|
||||
this(channelType, ANY_LOCAL_ADDR, nameServerAddresses);
|
||||
}
|
||||
|
||||
public DnsNameResolverGroup(
|
||||
Class<? extends DatagramChannel> channelType,
|
||||
InetSocketAddress localAddress, Iterable<InetSocketAddress> nameServerAddresses) {
|
||||
InetSocketAddress localAddress, DnsServerAddresses nameServerAddresses) {
|
||||
this(new ReflectiveChannelFactory<DatagramChannel>(channelType), localAddress, nameServerAddresses);
|
||||
}
|
||||
|
||||
public DnsNameResolverGroup(
|
||||
ChannelFactory<? extends DatagramChannel> channelFactory,
|
||||
Iterable<InetSocketAddress> nameServerAddresses) {
|
||||
ChannelFactory<? extends DatagramChannel> channelFactory, DnsServerAddresses nameServerAddresses) {
|
||||
this(channelFactory, ANY_LOCAL_ADDR, nameServerAddresses);
|
||||
}
|
||||
|
||||
public DnsNameResolverGroup(
|
||||
ChannelFactory<? extends DatagramChannel> channelFactory,
|
||||
InetSocketAddress localAddress, Iterable<InetSocketAddress> nameServerAddresses) {
|
||||
InetSocketAddress localAddress, DnsServerAddresses nameServerAddresses) {
|
||||
this.channelFactory = channelFactory;
|
||||
this.localAddress = localAddress;
|
||||
this.nameServerAddresses = nameServerAddresses;
|
||||
|
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2015 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package io.netty.resolver.dns;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
/**
|
||||
* An infinite stream of DNS server addresses.
|
||||
*/
|
||||
public interface DnsServerAddressStream {
|
||||
/**
|
||||
* Retrieves the next DNS server address from the stream.
|
||||
*/
|
||||
InetSocketAddress next();
|
||||
}
|
@ -16,35 +16,29 @@
|
||||
|
||||
package io.netty.resolver.dns;
|
||||
|
||||
import io.netty.util.internal.PlatformDependent;
|
||||
import io.netty.util.internal.ThreadLocalRandom;
|
||||
import io.netty.util.internal.logging.InternalLogger;
|
||||
import io.netty.util.internal.logging.InternalLoggerFactory;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
|
||||
|
||||
/**
|
||||
* Provides a sequence of DNS server addresses to {@link DnsNameResolver}. The {@link Iterator} created by the
|
||||
* {@link Iterable}s returned by the factory methods of this class is infinite, which means {@link Iterator#hasNext()}
|
||||
* will never return {@code false} and {@link Iterator#next()} will never raise a {@link NoSuchElementException}.
|
||||
* Provides an infinite sequence of DNS server addresses to {@link DnsNameResolver}.
|
||||
*/
|
||||
@SuppressWarnings("IteratorNextCanNotThrowNoSuchElementException")
|
||||
public final class DnsServerAddresses {
|
||||
public abstract class DnsServerAddresses {
|
||||
|
||||
private static final InternalLogger logger = InternalLoggerFactory.getInstance(DnsServerAddresses.class);
|
||||
|
||||
private static final List<InetSocketAddress> DEFAULT_NAME_SERVER_LIST;
|
||||
private static final InetSocketAddress[] DEFAULT_NAME_SERVER_ARRAY;
|
||||
private static final DnsServerAddresses DEFAULT_NAME_SERVERS;
|
||||
|
||||
static {
|
||||
final int DNS_PORT = 53;
|
||||
@ -57,11 +51,9 @@ public final class DnsServerAddresses {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
final List<String> list = (List<String>) nameservers.invoke(instance);
|
||||
final int size = list.size();
|
||||
for (int i = 0; i < size; i ++) {
|
||||
String dnsAddr = list.get(i);
|
||||
if (dnsAddr != null) {
|
||||
defaultNameServers.add(new InetSocketAddress(InetAddress.getByName(dnsAddr), DNS_PORT));
|
||||
for (String a: list) {
|
||||
if (a != null) {
|
||||
defaultNameServers.add(new InetSocketAddress(InetAddress.getByName(a), DNS_PORT));
|
||||
}
|
||||
}
|
||||
} catch (Exception ignore) {
|
||||
@ -88,106 +80,123 @@ public final class DnsServerAddresses {
|
||||
|
||||
DEFAULT_NAME_SERVER_LIST = Collections.unmodifiableList(defaultNameServers);
|
||||
DEFAULT_NAME_SERVER_ARRAY = defaultNameServers.toArray(new InetSocketAddress[defaultNameServers.size()]);
|
||||
DEFAULT_NAME_SERVERS = sequential(DEFAULT_NAME_SERVER_ARRAY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of the system DNS server addresses. If it failed to retrieve the list of the system DNS server
|
||||
* Returns the list of the system DNS server addresses. If it failed to retrieve the list of the system DNS server
|
||||
* addresses from the environment, it will return {@code "8.8.8.8"} and {@code "8.8.4.4"}, the addresses of the
|
||||
* Google public DNS servers. Note that the {@code Iterator} of the returned list is not infinite unlike other
|
||||
* factory methods in this class. To make the returned list infinite, pass it to the other factory method. e.g.
|
||||
* <pre>
|
||||
* addresses = {@link #sequential(Iterable) sequential}({@link #defaultAddresses()});
|
||||
* </pre>
|
||||
* Google public DNS servers.
|
||||
*/
|
||||
public static List<InetSocketAddress> defaultAddresses() {
|
||||
public static List<InetSocketAddress> defaultAddressList() {
|
||||
return DEFAULT_NAME_SERVER_LIST;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an infinite {@link Iterable} of the specified DNS server addresses, whose {@link Iterator} iterates
|
||||
* the DNS server addresses in a sequential order.
|
||||
* Returns the {@link DnsServerAddresses} that yields the system DNS server addresses sequentially. If it failed to
|
||||
* retrieve the list of the system DNS server addresses from the environment, it will use {@code "8.8.8.8"} and
|
||||
* {@code "8.8.4.4"}, the addresses of the Google public DNS servers.
|
||||
* <p>
|
||||
* This method has the same effect with the following code:
|
||||
* <pre>
|
||||
* DnsServerAddresses.sequential(DnsServerAddresses.defaultAddressList());
|
||||
* </pre>
|
||||
* </p>
|
||||
*/
|
||||
public static Iterable<InetSocketAddress> sequential(Iterable<? extends InetSocketAddress> addresses) {
|
||||
public static DnsServerAddresses defaultAddresses() {
|
||||
return DEFAULT_NAME_SERVERS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link DnsServerAddresses} that yields the specified {@code addresses} sequentially. Once the
|
||||
* last address is yielded, it will start again from the first address.
|
||||
*/
|
||||
public static DnsServerAddresses sequential(Iterable<? extends InetSocketAddress> addresses) {
|
||||
return sequential0(sanitize(addresses));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an infinite {@link Iterable} of the specified DNS server addresses, whose {@link Iterator} iterates
|
||||
* the DNS server addresses in a sequential order.
|
||||
* Returns the {@link DnsServerAddresses} that yields the specified {@code addresses} sequentially. Once the
|
||||
* last address is yielded, it will start again from the first address.
|
||||
*/
|
||||
public static Iterable<InetSocketAddress> sequential(InetSocketAddress... addresses) {
|
||||
public static DnsServerAddresses sequential(InetSocketAddress... addresses) {
|
||||
return sequential0(sanitize(addresses));
|
||||
}
|
||||
|
||||
private static Iterable<InetSocketAddress> sequential0(final InetSocketAddress[] addresses) {
|
||||
return new Iterable<InetSocketAddress>() {
|
||||
@Override
|
||||
public Iterator<InetSocketAddress> iterator() {
|
||||
return new SequentialAddressIterator(addresses, 0);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an infinite {@link Iterable} of the specified DNS server addresses, whose {@link Iterator} iterates
|
||||
* the DNS server addresses in a shuffled order.
|
||||
*/
|
||||
public static Iterable<InetSocketAddress> shuffled(Iterable<? extends InetSocketAddress> addresses) {
|
||||
return shuffled0(sanitize(addresses));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an infinite {@link Iterable} of the specified DNS server addresses, whose {@link Iterator} iterates
|
||||
* the DNS server addresses in a shuffled order.
|
||||
*/
|
||||
public static Iterable<InetSocketAddress> shuffled(InetSocketAddress... addresses) {
|
||||
return shuffled0(sanitize(addresses));
|
||||
}
|
||||
|
||||
private static Iterable<InetSocketAddress> shuffled0(final InetSocketAddress[] addresses) {
|
||||
private static DnsServerAddresses sequential0(final InetSocketAddress... addresses) {
|
||||
if (addresses.length == 1) {
|
||||
return singleton(addresses[0]);
|
||||
}
|
||||
|
||||
return new Iterable<InetSocketAddress>() {
|
||||
return new DefaultDnsServerAddresses("sequential", addresses) {
|
||||
@Override
|
||||
public Iterator<InetSocketAddress> iterator() {
|
||||
return new ShuffledAddressIterator(addresses);
|
||||
public DnsServerAddressStream stream() {
|
||||
return new SequentialDnsServerAddressStream(addresses, 0);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an infinite {@link Iterable} of the specified DNS server addresses, whose {@link Iterator} iterates
|
||||
* the DNS server addresses in a rotational order. It is similar to {@link #sequential(Iterable)}, but each
|
||||
* {@link Iterator} starts from a different starting point. For example, the first {@link Iterable#iterator()}
|
||||
* will iterate from the first DNS server address, the second one will iterate from the second DNS server address,
|
||||
* and so on.
|
||||
* Returns the {@link DnsServerAddresses} that yields the specified {@code address} in a shuffled order. Once all
|
||||
* addresses are yielded, the addresses are shuffled again.
|
||||
*/
|
||||
public static Iterable<InetSocketAddress> rotational(Iterable<? extends InetSocketAddress> addresses) {
|
||||
public static DnsServerAddresses shuffled(Iterable<? extends InetSocketAddress> addresses) {
|
||||
return shuffled0(sanitize(addresses));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link DnsServerAddresses} that yields the specified {@code addresses} in a shuffled order. Once all
|
||||
* addresses are yielded, the addresses are shuffled again.
|
||||
*/
|
||||
public static DnsServerAddresses shuffled(InetSocketAddress... addresses) {
|
||||
return shuffled0(sanitize(addresses));
|
||||
}
|
||||
|
||||
private static DnsServerAddresses shuffled0(final InetSocketAddress[] addresses) {
|
||||
if (addresses.length == 1) {
|
||||
return singleton(addresses[0]);
|
||||
}
|
||||
|
||||
return new DefaultDnsServerAddresses("shuffled", addresses) {
|
||||
@Override
|
||||
public DnsServerAddressStream stream() {
|
||||
return new ShuffledDnsServerAddressStream(addresses);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link DnsServerAddresses} that yields the specified {@code addresses} in a rotational sequential
|
||||
* order. It is similar to {@link #sequential(Iterable)}, but each {@link DnsServerAddressStream} starts from
|
||||
* a different starting point. For example, the first {@link #stream()} will start from the first address, the
|
||||
* second one will start from the second address, and so on.
|
||||
*/
|
||||
public static DnsServerAddresses rotational(Iterable<? extends InetSocketAddress> addresses) {
|
||||
return rotational0(sanitize(addresses));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an infinite {@link Iterable} of the specified DNS server addresses, whose {@link Iterator} iterates
|
||||
* the DNS server addresses in a rotational order. It is similar to {@link #sequential(Iterable)}, but each
|
||||
* {@link Iterator} starts from a different starting point. For example, the first {@link Iterable#iterator()}
|
||||
* will iterate from the first DNS server address, the second one will iterate from the second DNS server address,
|
||||
* and so on.
|
||||
* Returns the {@link DnsServerAddresses} that yields the specified {@code addresses} in a rotational sequential
|
||||
* order. It is similar to {@link #sequential(Iterable)}, but each {@link DnsServerAddressStream} starts from
|
||||
* a different starting point. For example, the first {@link #stream()} will start from the first address, the
|
||||
* second one will start from the second address, and so on.
|
||||
*/
|
||||
public static Iterable<InetSocketAddress> rotational(InetSocketAddress... addresses) {
|
||||
public static DnsServerAddresses rotational(InetSocketAddress... addresses) {
|
||||
return rotational0(sanitize(addresses));
|
||||
}
|
||||
|
||||
private static Iterable<InetSocketAddress> rotational0(final InetSocketAddress[] addresses) {
|
||||
return new RotationalAddresses(addresses);
|
||||
private static DnsServerAddresses rotational0(final InetSocketAddress[] addresses) {
|
||||
if (addresses.length == 1) {
|
||||
return singleton(addresses[0]);
|
||||
}
|
||||
|
||||
return new RotationalDnsServerAddresses(addresses);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an infinite {@link Iterable} of the specified DNS server address, whose {@link Iterator} always
|
||||
* return the same DNS server address.
|
||||
* Returns the {@link DnsServerAddresses} that yields only a single {@code address}.
|
||||
*/
|
||||
public static Iterable<InetSocketAddress> singleton(final InetSocketAddress address) {
|
||||
public static DnsServerAddresses singleton(final InetSocketAddress address) {
|
||||
if (address == null) {
|
||||
throw new NullPointerException("address");
|
||||
}
|
||||
@ -195,30 +204,7 @@ public final class DnsServerAddresses {
|
||||
throw new IllegalArgumentException("cannot use an unresolved DNS server address: " + address);
|
||||
}
|
||||
|
||||
return new Iterable<InetSocketAddress>() {
|
||||
|
||||
private final Iterator<InetSocketAddress> iterator = new Iterator<InetSocketAddress>() {
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetSocketAddress next() {
|
||||
return address;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public Iterator<InetSocketAddress> iterator() {
|
||||
return iterator;
|
||||
}
|
||||
};
|
||||
return new SingletonDnsServerAddresses(address);
|
||||
}
|
||||
|
||||
private static InetSocketAddress[] sanitize(Iterable<? extends InetSocketAddress> addresses) {
|
||||
@ -244,7 +230,7 @@ public final class DnsServerAddresses {
|
||||
}
|
||||
|
||||
if (list.isEmpty()) {
|
||||
return DEFAULT_NAME_SERVER_ARRAY;
|
||||
throw new IllegalArgumentException("empty addresses");
|
||||
}
|
||||
|
||||
return list.toArray(new InetSocketAddress[list.size()]);
|
||||
@ -273,123 +259,9 @@ public final class DnsServerAddresses {
|
||||
return list.toArray(new InetSocketAddress[list.size()]);
|
||||
}
|
||||
|
||||
private DnsServerAddresses() { }
|
||||
|
||||
private static final class SequentialAddressIterator implements Iterator<InetSocketAddress> {
|
||||
|
||||
private final InetSocketAddress[] addresses;
|
||||
private int i;
|
||||
|
||||
SequentialAddressIterator(InetSocketAddress[] addresses, int startIdx) {
|
||||
this.addresses = addresses;
|
||||
i = startIdx;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetSocketAddress next() {
|
||||
int i = this.i;
|
||||
InetSocketAddress next = addresses[i];
|
||||
if (++ i < addresses.length) {
|
||||
this.i = i;
|
||||
} else {
|
||||
this.i = 0;
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
private static final class ShuffledAddressIterator implements Iterator<InetSocketAddress> {
|
||||
|
||||
private final InetSocketAddress[] addresses;
|
||||
private int i;
|
||||
|
||||
ShuffledAddressIterator(InetSocketAddress[] addresses) {
|
||||
this.addresses = addresses.clone();
|
||||
|
||||
shuffle();
|
||||
}
|
||||
|
||||
private void shuffle() {
|
||||
final InetSocketAddress[] addresses = this.addresses;
|
||||
final Random r = ThreadLocalRandom.current();
|
||||
|
||||
for (int i = addresses.length - 1; i >= 0; i --) {
|
||||
InetSocketAddress tmp = addresses[i];
|
||||
int j = r.nextInt(i + 1);
|
||||
addresses[i] = addresses[j];
|
||||
addresses[j] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetSocketAddress next() {
|
||||
int i = this.i;
|
||||
InetSocketAddress next = addresses[i];
|
||||
if (++ i < addresses.length) {
|
||||
this.i = i;
|
||||
} else {
|
||||
this.i = 0;
|
||||
shuffle();
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
private static final class RotationalAddresses implements Iterable<InetSocketAddress> {
|
||||
|
||||
private static final AtomicIntegerFieldUpdater<RotationalAddresses> startIdxUpdater;
|
||||
|
||||
static {
|
||||
AtomicIntegerFieldUpdater<RotationalAddresses> updater =
|
||||
PlatformDependent.newAtomicIntegerFieldUpdater(RotationalAddresses.class, "startIdx");
|
||||
|
||||
if (updater == null) {
|
||||
updater = AtomicIntegerFieldUpdater.newUpdater(RotationalAddresses.class, "startIdx");
|
||||
}
|
||||
|
||||
startIdxUpdater = updater;
|
||||
}
|
||||
|
||||
private final InetSocketAddress[] addresses;
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
private volatile int startIdx;
|
||||
|
||||
RotationalAddresses(InetSocketAddress[] addresses) {
|
||||
this.addresses = addresses;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<InetSocketAddress> iterator() {
|
||||
for (;;) {
|
||||
int curStartIdx = startIdx;
|
||||
int nextStartIdx = curStartIdx + 1;
|
||||
if (nextStartIdx >= addresses.length) {
|
||||
nextStartIdx = 0;
|
||||
}
|
||||
if (startIdxUpdater.compareAndSet(this, curStartIdx, nextStartIdx)) {
|
||||
return new SequentialAddressIterator(addresses, curStartIdx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Starts a new infinite stream of DNS server addresses. This method is invoked by {@link DnsNameResolver} on every
|
||||
* uncached {@link DnsNameResolver#resolve(SocketAddress)} or {@link DnsNameResolver#resolveAll(SocketAddress)}.
|
||||
*/
|
||||
public abstract DnsServerAddressStream stream();
|
||||
}
|
||||
|
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2015 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package io.netty.resolver.dns;
|
||||
|
||||
import io.netty.util.internal.PlatformDependent;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
|
||||
|
||||
final class RotationalDnsServerAddresses extends DefaultDnsServerAddresses {
|
||||
|
||||
private static final AtomicIntegerFieldUpdater<RotationalDnsServerAddresses> startIdxUpdater;
|
||||
|
||||
static {
|
||||
AtomicIntegerFieldUpdater<RotationalDnsServerAddresses> updater =
|
||||
PlatformDependent.newAtomicIntegerFieldUpdater(RotationalDnsServerAddresses.class, "startIdx");
|
||||
|
||||
if (updater == null) {
|
||||
updater = AtomicIntegerFieldUpdater.newUpdater(RotationalDnsServerAddresses.class, "startIdx");
|
||||
}
|
||||
|
||||
startIdxUpdater = updater;
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
private volatile int startIdx;
|
||||
|
||||
RotationalDnsServerAddresses(InetSocketAddress[] addresses) {
|
||||
super("rotational", addresses);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DnsServerAddressStream stream() {
|
||||
for (;;) {
|
||||
int curStartIdx = startIdx;
|
||||
int nextStartIdx = curStartIdx + 1;
|
||||
if (nextStartIdx >= addresses.length) {
|
||||
nextStartIdx = 0;
|
||||
}
|
||||
if (startIdxUpdater.compareAndSet(this, curStartIdx, nextStartIdx)) {
|
||||
return new SequentialDnsServerAddressStream(addresses, curStartIdx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2015 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package io.netty.resolver.dns;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
final class SequentialDnsServerAddressStream implements DnsServerAddressStream {
|
||||
|
||||
private final InetSocketAddress[] addresses;
|
||||
private int i;
|
||||
|
||||
SequentialDnsServerAddressStream(InetSocketAddress[] addresses, int startIdx) {
|
||||
this.addresses = addresses;
|
||||
i = startIdx;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetSocketAddress next() {
|
||||
int i = this.i;
|
||||
InetSocketAddress next = addresses[i];
|
||||
if (++ i < addresses.length) {
|
||||
this.i = i;
|
||||
} else {
|
||||
this.i = 0;
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toString("sequential", i, addresses);
|
||||
}
|
||||
|
||||
static String toString(String type, int index, InetSocketAddress[] addresses) {
|
||||
final StringBuilder buf = new StringBuilder(type.length() + 2 + addresses.length * 16);
|
||||
buf.append(type).append("(index: ").append(index);
|
||||
buf.append(", addrs: (");
|
||||
for (InetSocketAddress a: addresses) {
|
||||
buf.append(a).append(", ");
|
||||
}
|
||||
|
||||
buf.setLength(buf.length() - 2);
|
||||
buf.append("))");
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2015 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package io.netty.resolver.dns;
|
||||
|
||||
import io.netty.util.internal.ThreadLocalRandom;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Random;
|
||||
|
||||
final class ShuffledDnsServerAddressStream implements DnsServerAddressStream {
|
||||
|
||||
private final InetSocketAddress[] addresses;
|
||||
private int i;
|
||||
|
||||
ShuffledDnsServerAddressStream(InetSocketAddress[] addresses) {
|
||||
this.addresses = addresses.clone();
|
||||
|
||||
shuffle();
|
||||
}
|
||||
|
||||
private void shuffle() {
|
||||
final InetSocketAddress[] addresses = this.addresses;
|
||||
final Random r = ThreadLocalRandom.current();
|
||||
|
||||
for (int i = addresses.length - 1; i >= 0; i --) {
|
||||
InetSocketAddress tmp = addresses[i];
|
||||
int j = r.nextInt(i + 1);
|
||||
addresses[i] = addresses[j];
|
||||
addresses[j] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetSocketAddress next() {
|
||||
int i = this.i;
|
||||
InetSocketAddress next = addresses[i];
|
||||
if (++ i < addresses.length) {
|
||||
this.i = i;
|
||||
} else {
|
||||
this.i = 0;
|
||||
shuffle();
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return SequentialDnsServerAddressStream.toString("shuffled", i, addresses);
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2015 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package io.netty.resolver.dns;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
final class SingletonDnsServerAddresses extends DnsServerAddresses {
|
||||
|
||||
private final InetSocketAddress address;
|
||||
private final String strVal;
|
||||
|
||||
private final DnsServerAddressStream stream = new DnsServerAddressStream() {
|
||||
@Override
|
||||
public InetSocketAddress next() {
|
||||
return address;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return SingletonDnsServerAddresses.this.toString();
|
||||
}
|
||||
};
|
||||
|
||||
SingletonDnsServerAddresses(InetSocketAddress address) {
|
||||
this.address = address;
|
||||
strVal = new StringBuilder(32).append("singleton(").append(address).append(')').toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DnsServerAddressStream stream() {
|
||||
return stream;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return strVal;
|
||||
}
|
||||
}
|
@ -22,7 +22,6 @@ import org.junit.Test;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Collections;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
@ -36,16 +35,16 @@ public class DnsServerAddressesTest {
|
||||
|
||||
@Test
|
||||
public void testDefaultAddresses() {
|
||||
assertThat(DnsServerAddresses.defaultAddresses().size(), is(greaterThan(0)));
|
||||
assertThat(DnsServerAddresses.defaultAddressList().size(), is(greaterThan(0)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSequential() {
|
||||
Iterable<InetSocketAddress> seq = DnsServerAddresses.sequential(ADDR1, ADDR2, ADDR3);
|
||||
assertThat(seq.iterator(), is(not(sameInstance(seq.iterator()))));
|
||||
DnsServerAddresses seq = DnsServerAddresses.sequential(ADDR1, ADDR2, ADDR3);
|
||||
assertThat(seq.stream(), is(not(sameInstance(seq.stream()))));
|
||||
|
||||
for (int j = 0; j < 2; j ++) {
|
||||
Iterator<InetSocketAddress> i = seq.iterator();
|
||||
DnsServerAddressStream i = seq.stream();
|
||||
assertNext(i, ADDR1);
|
||||
assertNext(i, ADDR2);
|
||||
assertNext(i, ADDR3);
|
||||
@ -57,9 +56,9 @@ public class DnsServerAddressesTest {
|
||||
|
||||
@Test
|
||||
public void testRotational() {
|
||||
Iterable<InetSocketAddress> seq = DnsServerAddresses.rotational(ADDR1, ADDR2, ADDR3);
|
||||
DnsServerAddresses seq = DnsServerAddresses.rotational(ADDR1, ADDR2, ADDR3);
|
||||
|
||||
Iterator<InetSocketAddress> i = seq.iterator();
|
||||
DnsServerAddressStream i = seq.stream();
|
||||
assertNext(i, ADDR1);
|
||||
assertNext(i, ADDR2);
|
||||
assertNext(i, ADDR3);
|
||||
@ -67,7 +66,7 @@ public class DnsServerAddressesTest {
|
||||
assertNext(i, ADDR2);
|
||||
assertNext(i, ADDR3);
|
||||
|
||||
i = seq.iterator();
|
||||
i = seq.stream();
|
||||
assertNext(i, ADDR2);
|
||||
assertNext(i, ADDR3);
|
||||
assertNext(i, ADDR1);
|
||||
@ -75,7 +74,7 @@ public class DnsServerAddressesTest {
|
||||
assertNext(i, ADDR3);
|
||||
assertNext(i, ADDR1);
|
||||
|
||||
i = seq.iterator();
|
||||
i = seq.stream();
|
||||
assertNext(i, ADDR3);
|
||||
assertNext(i, ADDR1);
|
||||
assertNext(i, ADDR2);
|
||||
@ -83,7 +82,7 @@ public class DnsServerAddressesTest {
|
||||
assertNext(i, ADDR1);
|
||||
assertNext(i, ADDR2);
|
||||
|
||||
i = seq.iterator();
|
||||
i = seq.stream();
|
||||
assertNext(i, ADDR1);
|
||||
assertNext(i, ADDR2);
|
||||
assertNext(i, ADDR3);
|
||||
@ -94,36 +93,34 @@ public class DnsServerAddressesTest {
|
||||
|
||||
@Test
|
||||
public void testShuffled() {
|
||||
Iterable<InetSocketAddress> seq = DnsServerAddresses.shuffled(ADDR1, ADDR2, ADDR3);
|
||||
DnsServerAddresses seq = DnsServerAddresses.shuffled(ADDR1, ADDR2, ADDR3);
|
||||
|
||||
// Ensure that all three addresses are returned by the iterator.
|
||||
// In theory, this test can fail at extremely low chance, but we don't really care.
|
||||
Set<InetSocketAddress> set = Collections.newSetFromMap(new IdentityHashMap<InetSocketAddress, Boolean>());
|
||||
Iterator<InetSocketAddress> i = seq.iterator();
|
||||
DnsServerAddressStream i = seq.stream();
|
||||
for (int j = 0; j < 1048576; j ++) {
|
||||
assertThat(i.hasNext(), is(true));
|
||||
set.add(i.next());
|
||||
}
|
||||
|
||||
assertThat(set.size(), is(3));
|
||||
assertThat(seq.iterator(), is(not(sameInstance(seq.iterator()))));
|
||||
assertThat(seq.stream(), is(not(sameInstance(seq.stream()))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingleton() {
|
||||
Iterable<InetSocketAddress> seq = DnsServerAddresses.singleton(ADDR1);
|
||||
DnsServerAddresses seq = DnsServerAddresses.singleton(ADDR1);
|
||||
|
||||
// Should return the same iterator instance for least possible footprint.
|
||||
assertThat(seq.iterator(), is(sameInstance(seq.iterator())));
|
||||
assertThat(seq.stream(), is(sameInstance(seq.stream())));
|
||||
|
||||
Iterator<InetSocketAddress> i = seq.iterator();
|
||||
DnsServerAddressStream i = seq.stream();
|
||||
assertNext(i, ADDR1);
|
||||
assertNext(i, ADDR1);
|
||||
assertNext(i, ADDR1);
|
||||
}
|
||||
|
||||
private static void assertNext(Iterator<InetSocketAddress> i, InetSocketAddress addr) {
|
||||
assertThat(i.hasNext(), is(true));
|
||||
private static void assertNext(DnsServerAddressStream i, InetSocketAddress addr) {
|
||||
assertThat(i.next(), is(sameInstance(addr)));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user