Better document in code InetAddressAndPort usage post 7544

Patch by Ariel Weisberg; Reviewed by Jon Haddad for CASSANDRA-14226
This commit is contained in:
Ariel Weisberg 2018-02-09 17:38:52 -05:00
parent 1188fcb082
commit 518ddbf9d2
5 changed files with 101 additions and 25 deletions

View File

@ -1,4 +1,5 @@
4.0
* Better document in code InetAddressAndPort usage post 7544, incorporate port into UUIDGen node (CASSANDRA-14226)
* Fix sstablemetadata date string for minLocalDeletionTime (CASSANDRA-14132)
* Make it possible to change neverPurgeTombstones during runtime (CASSANDRA-14214)
* Remove GossipDigestSynVerbHandler#doSort() (CASSANDRA-14174)

View File

@ -128,6 +128,13 @@ public class Config
public boolean listen_on_broadcast_address = false;
public String internode_authenticator;
/*
* RPC address and interface refer to the address/interface used for the native protocol used to communicate with
* clients. It's still called RPC in some places even though Thrift RPC is gone. If you see references to native
* address or native port it's derived from the RPC address configuration.
*
* native_transport_port is the port that is paired with RPC address to bind on.
*/
public String rpc_address;
public String rpc_interface;
public boolean rpc_interface_prefer_ipv6 = false;

View File

@ -1725,6 +1725,12 @@ public class DatabaseDescriptor
broadcastAddress = broadcastAdd;
}
/**
* This is the address used to bind for the native protocol to communicate with clients. Most usages in the code
* refer to it as native address although some places still call it RPC address. It's not thrift RPC anymore
* so native is more appropriate. The address alone is not enough to uniquely identify this instance because
* multiple instances might use the same interface with different ports.
*/
public static InetAddress getRpcAddress()
{
return rpcAddress;
@ -1736,7 +1742,12 @@ public class DatabaseDescriptor
}
/**
* May be null, please use {@link FBUtilities#getBroadcastRpcAddress()} instead.
* This is the address used to reach this instance for the native protocol to communicate with clients. Most usages in the code
* refer to it as native address although some places still call it RPC address. It's not thrift RPC anymore
* so native is more appropriate. The address alone is not enough to uniquely identify this instance because
* multiple instances might use the same interface with different ports.
*
* May be null, please use {@link FBUtilities#getBroadcastNativeAddressAndPort()} instead.
*/
public static InetAddress getBroadcastRpcAddress()
{
@ -1763,6 +1774,10 @@ public class DatabaseDescriptor
return conf.start_native_transport;
}
/**
* This is the port used with RPC address for the native protocol to communicate with clients. Now that thrift RPC
* is no longer in use there is no RPC port.
*/
public static int getNativeTransportPort()
{
return Integer.parseInt(System.getProperty(Config.PROPERTY_PREFIX + "native_transport_port", Integer.toString(conf.native_transport_port)));

View File

@ -96,7 +96,8 @@ public class FBUtilities
public static final int MAX_UNSIGNED_SHORT = 0xFFFF;
/**
* Please use getJustBroadcastAddress instead. You need this only when you have to listen/connect.
* Please use getJustBroadcastAddress instead. You need this only when you have to listen/connect. It's also missing
* the port you should be using. 99% of code doesn't want this.
*/
public static InetAddress getJustLocalAddress()
{
@ -114,6 +115,10 @@ public class FBUtilities
return localInetAddress;
}
/**
* The address and port to listen on for intra-cluster storage traffic (not client). Use this to get the correct
* stuff to listen on for intra-cluster communication.
*/
public static InetAddressAndPort getLocalAddressAndPort()
{
if (localInetAddressAndPort == null)
@ -123,6 +128,10 @@ public class FBUtilities
return localInetAddressAndPort;
}
/**
* Retrieve just the broadcast address but not the port. This is almost always the wrong thing to be using because
* it's ambiguous since you need the address and port to identify a node. You want getBroadcastAddressAndPort
*/
public static InetAddress getJustBroadcastAddress()
{
if (broadcastInetAddress == null)
@ -132,6 +141,11 @@ public class FBUtilities
return broadcastInetAddress;
}
/**
* Get the broadcast address and port for intra-cluster storage traffic. This the address to advertise that uniquely
* identifies the node and is reachable from everywhere. This is the one you want unless you are trying to connect
* to the local address specifically.
*/
public static InetAddressAndPort getBroadcastAddressAndPort()
{
if (broadcastInetAddressAndPort == null)
@ -150,6 +164,10 @@ public class FBUtilities
broadcastInetAddressAndPort = InetAddressAndPort.getByAddress(broadcastInetAddress);
}
/**
* This returns the address that is bound to for the native protocol for communicating with clients. This is ambiguous
* because it doesn't include the port and it's almost always the wrong thing to be using you want getBroadcastNativeAddressAndPort
*/
public static InetAddress getJustBroadcastNativeAddress()
{
if (broadcastNativeAddress == null)
@ -159,6 +177,10 @@ public class FBUtilities
return broadcastNativeAddress;
}
/**
* This returns the address that is bound to for the native protocol for communicating with clients. This is almost
* always what you need to identify a node and how to connect to it as a client.
*/
public static InetAddressAndPort getBroadcastNativeAddressAndPort()
{
if (broadcastNativeAddressAndPort == null)
@ -167,25 +189,6 @@ public class FBUtilities
return broadcastNativeAddressAndPort;
}
public static Collection<InetAddress> getAllLocalAddresses()
{
Set<InetAddress> localAddresses = new HashSet<InetAddress>();
try
{
Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces();
if (nets != null)
{
while (nets.hasMoreElements())
localAddresses.addAll(Collections.list(nets.nextElement().getInetAddresses()));
}
}
catch (SocketException e)
{
throw new AssertionError(e);
}
return localAddresses;
}
public static String getNetworkInterface(InetAddress localAddress)
{
try

View File

@ -18,19 +18,31 @@
package org.apache.cassandra.utils;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.security.SecureRandom;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.hash.Hasher;
import com.google.common.hash.Hashing;
import com.google.common.primitives.Ints;
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.locator.InetAddressAndPort;
/**
* The goods are here: www.ietf.org/rfc/rfc4122.txt.
*/
@ -361,7 +373,7 @@ public class UUIDGen
* instanciation and the UUID generator is used in Stress for instance,
* where we don't want to require the yaml.
*/
Collection<InetAddress> localAddresses = FBUtilities.getAllLocalAddresses();
Collection<InetAddressAndPort> localAddresses = getAllLocalAddresses();
if (localAddresses.isEmpty())
throw new RuntimeException("Cannot generate the node component of the UUID because cannot retrieve any IP addresses.");
@ -377,12 +389,15 @@ public class UUIDGen
return node | 0x0000010000000000L;
}
private static byte[] hash(Collection<InetAddress> data)
private static byte[] hash(Collection<InetAddressAndPort> data)
{
// Identify the host.
Hasher hasher = Hashing.md5().newHasher();
for(InetAddress addr : data)
hasher.putBytes(addr.getAddress());
for(InetAddressAndPort addr : data)
{
hasher.putBytes(addr.addressBytes);
hasher.putInt(addr.port);
}
// Identify the process on the load: we use both the PID and class loader hash.
long pid = NativeLibrary.getProcessID();
@ -396,6 +411,41 @@ public class UUIDGen
return hasher.hash().asBytes();
}
/**
* Helper function used exclusively by UUIDGen to create
**/
public static Collection<InetAddressAndPort> getAllLocalAddresses()
{
Set<InetAddressAndPort> localAddresses = new HashSet<>();
try
{
Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces();
if (nets != null)
{
while (nets.hasMoreElements())
{
Function<InetAddress, InetAddressAndPort> converter =
address -> InetAddressAndPort.getByAddressOverrideDefaults(address, 0);
List<InetAddressAndPort> addresses =
Collections.list(nets.nextElement().getInetAddresses()).stream().map(converter).collect(Collectors.toList());
localAddresses.addAll(addresses);
}
}
}
catch (SocketException e)
{
throw new AssertionError(e);
}
if (DatabaseDescriptor.isDaemonInitialized())
{
localAddresses.add(FBUtilities.getBroadcastAddressAndPort());
localAddresses.add(FBUtilities.getBroadcastNativeAddressAndPort());
localAddresses.add(FBUtilities.getLocalAddressAndPort());
}
return localAddresses;
}
}
// for the curious, here is how I generated START_EPOCH