You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by sn...@apache.org on 2015/03/17 19:33:03 UTC
[1/3] cassandra git commit: DatabaseDescriptor throws NPE when
rpc_interface is used
Repository: cassandra
Updated Branches:
refs/heads/cassandra-2.1 c0f159b82 -> 89cdfd8e0
refs/heads/trunk ac9ccfdf7 -> 8d570fa79
DatabaseDescriptor throws NPE when rpc_interface is used
patch by Ariel Weisberg; reviewed by Carl Yeksigian for CASSANDRA-8839
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/89cdfd8e
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/89cdfd8e
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/89cdfd8e
Branch: refs/heads/cassandra-2.1
Commit: 89cdfd8e075d8883d776d7f881735f1c25e3cb54
Parents: c0f159b
Author: Ariel Weisberg <ar...@weisberg.ws>
Authored: Tue Mar 17 19:27:54 2015 +0100
Committer: Robert Stupp <sn...@snazy.de>
Committed: Tue Mar 17 19:27:54 2015 +0100
----------------------------------------------------------------------
CHANGES.txt | 1 +
conf/cassandra.yaml | 12 ++
.../org/apache/cassandra/config/Config.java | 6 +-
.../cassandra/config/DatabaseDescriptor.java | 205 +++++++++++--------
.../config/YamlConfigurationLoader.java | 16 +-
.../config/DatabaseDescriptorTest.java | 139 ++++++++++++-
6 files changed, 277 insertions(+), 102 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cassandra/blob/89cdfd8e/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 7b8e0ad..30bf698 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
2.1.4
+ * DatabaseDescriptor throws NPE when rpc_interface is used (CASSANDRA-8839)
* Don't check if an sstable is live for offline compactions (CASSANDRA-8841)
* Don't set clientMode in SSTableLoader (CASSANDRA-8238)
* Fix SSTableRewriter with disabled early open (CASSANDRA-8535)
http://git-wip-us.apache.org/repos/asf/cassandra/blob/89cdfd8e/conf/cassandra.yaml
----------------------------------------------------------------------
diff --git a/conf/cassandra.yaml b/conf/cassandra.yaml
index cea12b3..2b43ba7 100644
--- a/conf/cassandra.yaml
+++ b/conf/cassandra.yaml
@@ -370,8 +370,14 @@ ssl_storage_port: 7001
# address associated with the hostname (it might not be).
#
# Setting listen_address to 0.0.0.0 is always wrong.
+#
+# If you choose to specify the interface by name and the interface has an ipv4 and an ipv6 address
+# you can specify which should be chosen using listen_interface_prefer_ipv6. If false the first ipv4
+# address will be used. If true the first ipv6 address will be used. Defaults to false preferring
+# ipv4. If there is only one address it will be selected regardless of ipv4/ipv6.
listen_address: localhost
# listen_interface: eth0
+# listen_interface_prefer_ipv6: false
# Address to broadcast to other Cassandra nodes
# Leaving this blank will set it to the same value as listen_address
@@ -422,8 +428,14 @@ start_rpc: true
# set broadcast_rpc_address to a value other than 0.0.0.0.
#
# For security reasons, you should not expose this port to the internet. Firewall it if needed.
+#
+# If you choose to specify the interface by name and the interface has an ipv4 and an ipv6 address
+# you can specify which should be chosen using rpc_interface_prefer_ipv6. If false the first ipv4
+# address will be used. If true the first ipv6 address will be used. Defaults to false preferring
+# ipv4. If there is only one address it will be selected regardless of ipv4/ipv6.
rpc_address: localhost
# rpc_interface: eth1
+# rpc_interface_prefer_ipv6: false
# port for Thrift to listen for clients on
rpc_port: 9160
http://git-wip-us.apache.org/repos/asf/cassandra/blob/89cdfd8e/src/java/org/apache/cassandra/config/Config.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/config/Config.java b/src/java/org/apache/cassandra/config/Config.java
index ccd4467..fbbd1dd 100644
--- a/src/java/org/apache/cassandra/config/Config.java
+++ b/src/java/org/apache/cassandra/config/Config.java
@@ -34,7 +34,7 @@ import org.apache.cassandra.utils.FBUtilities;
/**
* A class that contains configuration properties for the cassandra node it runs within.
- *
+ *
* Properties declared as volatile can be mutated via JMX.
*/
public class Config
@@ -101,12 +101,14 @@ public class Config
public Integer ssl_storage_port = 7001;
public String listen_address;
public String listen_interface;
+ public Boolean listen_interface_prefer_ipv6 = false;
public String broadcast_address;
public String internode_authenticator;
public Boolean start_rpc = true;
public String rpc_address;
public String rpc_interface;
+ public Boolean rpc_interface_prefer_ipv6 = false;
public String broadcast_rpc_address;
public Integer rpc_port = 9160;
public Integer rpc_listen_backlog = 50;
@@ -155,7 +157,7 @@ public class Config
public Double commitlog_sync_batch_window_in_ms;
public Integer commitlog_sync_period_in_ms;
public int commitlog_segment_size_in_mb = 32;
-
+
@Deprecated
public int commitlog_periodic_queue_size = -1;
http://git-wip-us.apache.org/repos/asf/cassandra/blob/89cdfd8e/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
index 4426f20..65cec9c 100644
--- a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
+++ b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
@@ -20,6 +20,8 @@ package org.apache.cassandra.config;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
@@ -38,6 +40,7 @@ import java.util.UUID;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableSet;
import com.google.common.primitives.Longs;
+
import org.apache.cassandra.thrift.ThriftServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -158,7 +161,7 @@ public class DatabaseDescriptor
return loader.loadConfig();
}
- private static InetAddress getNetworkInterfaceAddress(String intf, String configName) throws ConfigurationException
+ private static InetAddress getNetworkInterfaceAddress(String intf, String configName, boolean preferIPv6) throws ConfigurationException
{
try
{
@@ -168,9 +171,18 @@ public class DatabaseDescriptor
Enumeration<InetAddress> addrs = ni.getInetAddresses();
if (!addrs.hasMoreElements())
throw new ConfigurationException("Configured " + configName + " \"" + intf + "\" was found, but had no addresses");
- InetAddress retval = listenAddress = addrs.nextElement();
- if (addrs.hasMoreElements())
- throw new ConfigurationException("Configured " + configName + " \"" + intf + "\" can't have more than one address");
+
+ /*
+ * Try to return the first address of the preferred type, otherwise return the first address
+ */
+ InetAddress retval = null;
+ while (addrs.hasMoreElements())
+ {
+ InetAddress temp = addrs.nextElement();
+ if (preferIPv6 && temp.getClass() == Inet6Address.class) return temp;
+ if (!preferIPv6 && temp.getClass() == Inet4Address.class) return temp;
+ if (retval == null) retval = temp;
+ }
return retval;
}
catch (SocketException e)
@@ -179,6 +191,103 @@ public class DatabaseDescriptor
}
}
+ @VisibleForTesting
+ static void applyAddressConfig(Config config) throws ConfigurationException
+ {
+ listenAddress = null;
+ rpcAddress = null;
+ broadcastAddress = null;
+ broadcastRpcAddress = null;
+
+ /* Local IP, hostname or interface to bind services to */
+ if (config.listen_address != null && config.listen_interface != null)
+ {
+ throw new ConfigurationException("Set listen_address OR listen_interface, not both");
+ }
+ else if (config.listen_address != null)
+ {
+ try
+ {
+ listenAddress = InetAddress.getByName(config.listen_address);
+ }
+ catch (UnknownHostException e)
+ {
+ throw new ConfigurationException("Unknown listen_address '" + config.listen_address + "'");
+ }
+
+ if (listenAddress.isAnyLocalAddress())
+ throw new ConfigurationException("listen_address cannot be a wildcard address (" + config.listen_address + ")!");
+ }
+ else if (config.listen_interface != null)
+ {
+ listenAddress = getNetworkInterfaceAddress(config.listen_interface, "listen_interface", config.listen_interface_prefer_ipv6);
+ }
+
+ /* Gossip Address to broadcast */
+ if (config.broadcast_address != null)
+ {
+ try
+ {
+ broadcastAddress = InetAddress.getByName(config.broadcast_address);
+ }
+ catch (UnknownHostException e)
+ {
+ throw new ConfigurationException("Unknown broadcast_address '" + config.broadcast_address + "'");
+ }
+
+ if (broadcastAddress.isAnyLocalAddress())
+ throw new ConfigurationException("broadcast_address cannot be a wildcard address (" + config.broadcast_address + ")!");
+ }
+
+ /* Local IP, hostname or interface to bind RPC server to */
+ if (config.rpc_address != null && config.rpc_interface != null)
+ {
+ throw new ConfigurationException("Set rpc_address OR rpc_interface, not both");
+ }
+ else if (config.rpc_address != null)
+ {
+ try
+ {
+ rpcAddress = InetAddress.getByName(config.rpc_address);
+ }
+ catch (UnknownHostException e)
+ {
+ throw new ConfigurationException("Unknown host in rpc_address " + config.rpc_address);
+ }
+ }
+ else if (config.rpc_interface != null)
+ {
+ rpcAddress = getNetworkInterfaceAddress(config.rpc_interface, "rpc_interface", config.rpc_interface_prefer_ipv6);
+ }
+ else
+ {
+ rpcAddress = FBUtilities.getLocalAddress();
+ }
+
+ /* RPC address to broadcast */
+ if (config.broadcast_rpc_address != null)
+ {
+ try
+ {
+ broadcastRpcAddress = InetAddress.getByName(config.broadcast_rpc_address);
+ }
+ catch (UnknownHostException e)
+ {
+ throw new ConfigurationException("Unknown broadcast_rpc_address '" + config.broadcast_rpc_address + "'");
+ }
+
+ if (broadcastRpcAddress.isAnyLocalAddress())
+ throw new ConfigurationException("broadcast_rpc_address cannot be a wildcard address (" + config.broadcast_rpc_address + ")!");
+ }
+ else
+ {
+ if (rpcAddress.isAnyLocalAddress())
+ throw new ConfigurationException("If rpc_address is set to a wildcard address (" + config.rpc_address + "), then " +
+ "you must set broadcast_rpc_address to a value other than " + config.rpc_address);
+ broadcastRpcAddress = rpcAddress;
+ }
+ }
+
private static void applyConfig(Config config) throws ConfigurationException
{
conf = config;
@@ -326,93 +435,7 @@ public class DatabaseDescriptor
else
logger.info("Global memtable off-heap threshold is enabled at {}MB", conf.memtable_offheap_space_in_mb);
- /* Local IP, hostname or interface to bind services to */
- if (conf.listen_address != null && conf.listen_interface != null)
- {
- throw new ConfigurationException("Set listen_address OR listen_interface, not both");
- }
- else if (conf.listen_address != null)
- {
- try
- {
- listenAddress = InetAddress.getByName(conf.listen_address);
- }
- catch (UnknownHostException e)
- {
- throw new ConfigurationException("Unknown listen_address '" + conf.listen_address + "'");
- }
-
- if (listenAddress.isAnyLocalAddress())
- throw new ConfigurationException("listen_address cannot be a wildcard address (" + conf.listen_address + ")!");
- }
- else if (conf.listen_interface != null)
- {
- listenAddress = getNetworkInterfaceAddress(conf.listen_interface, "listen_interface");
- }
-
- /* Gossip Address to broadcast */
- if (conf.broadcast_address != null)
- {
- try
- {
- broadcastAddress = InetAddress.getByName(conf.broadcast_address);
- }
- catch (UnknownHostException e)
- {
- throw new ConfigurationException("Unknown broadcast_address '" + conf.broadcast_address + "'");
- }
-
- if (broadcastAddress.isAnyLocalAddress())
- throw new ConfigurationException("broadcast_address cannot be a wildcard address (" + conf.broadcast_address + ")!");
- }
-
- /* Local IP, hostname or interface to bind RPC server to */
- if (conf.rpc_address != null && conf.rpc_interface != null)
- {
- throw new ConfigurationException("Set rpc_address OR rpc_interface, not both");
- }
- else if (conf.rpc_address != null)
- {
- try
- {
- rpcAddress = InetAddress.getByName(conf.rpc_address);
- }
- catch (UnknownHostException e)
- {
- throw new ConfigurationException("Unknown host in rpc_address " + conf.rpc_address);
- }
- }
- else if (conf.rpc_interface != null)
- {
- listenAddress = getNetworkInterfaceAddress(conf.rpc_interface, "rpc_interface");
- }
- else
- {
- rpcAddress = FBUtilities.getLocalAddress();
- }
-
- /* RPC address to broadcast */
- if (conf.broadcast_rpc_address != null)
- {
- try
- {
- broadcastRpcAddress = InetAddress.getByName(conf.broadcast_rpc_address);
- }
- catch (UnknownHostException e)
- {
- throw new ConfigurationException("Unknown broadcast_rpc_address '" + conf.broadcast_rpc_address + "'");
- }
-
- if (broadcastRpcAddress.isAnyLocalAddress())
- throw new ConfigurationException("broadcast_rpc_address cannot be a wildcard address (" + conf.broadcast_rpc_address + ")!");
- }
- else
- {
- if (rpcAddress.isAnyLocalAddress())
- throw new ConfigurationException("If rpc_address is set to a wildcard address (" + conf.rpc_address + "), then " +
- "you must set broadcast_rpc_address to a value other than " + conf.rpc_address);
- broadcastRpcAddress = rpcAddress;
- }
+ applyAddressConfig(config);
if (conf.thrift_framed_transport_size_in_mb <= 0)
throw new ConfigurationException("thrift_framed_transport_size_in_mb must be positive");
http://git-wip-us.apache.org/repos/asf/cassandra/blob/89cdfd8e/src/java/org/apache/cassandra/config/YamlConfigurationLoader.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/config/YamlConfigurationLoader.java b/src/java/org/apache/cassandra/config/YamlConfigurationLoader.java
index e222046..0061926 100644
--- a/src/java/org/apache/cassandra/config/YamlConfigurationLoader.java
+++ b/src/java/org/apache/cassandra/config/YamlConfigurationLoader.java
@@ -50,7 +50,7 @@ public class YamlConfigurationLoader implements ConfigurationLoader
/**
* Inspect the classpath to find storage configuration file
*/
- private URL getStorageConfigURL() throws ConfigurationException
+ static URL getStorageConfigURL() throws ConfigurationException
{
String configUrl = System.getProperty("cassandra.config");
if (configUrl == null)
@@ -100,7 +100,7 @@ public class YamlConfigurationLoader implements ConfigurationLoader
// getStorageConfigURL should have ruled this out
throw new AssertionError(e);
}
-
+
logConfig(configBytes);
org.yaml.snakeyaml.constructor.Constructor constructor = new org.yaml.snakeyaml.constructor.Constructor(Config.class);
@@ -134,16 +134,16 @@ public class YamlConfigurationLoader implements ConfigurationLoader
}
logger.info("Node configuration:[" + Joiner.on("; ").join(configMap.entrySet()) + "]");
}
-
- private static class MissingPropertiesChecker extends PropertyUtils
+
+ private static class MissingPropertiesChecker extends PropertyUtils
{
private final Set<String> missingProperties = new HashSet<>();
-
+
public MissingPropertiesChecker()
{
setSkipMissingProperties(true);
}
-
+
@Override
public Property getProperty(Class<? extends Object> type, String name) throws IntrospectionException
{
@@ -154,10 +154,10 @@ public class YamlConfigurationLoader implements ConfigurationLoader
}
return result;
}
-
+
public void check() throws ConfigurationException
{
- if (!missingProperties.isEmpty())
+ if (!missingProperties.isEmpty())
{
throw new ConfigurationException("Invalid yaml. Please remove properties " + missingProperties + " from your cassandra.yaml");
}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/89cdfd8e/test/unit/org/apache/cassandra/config/DatabaseDescriptorTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/config/DatabaseDescriptorTest.java b/test/unit/org/apache/cassandra/config/DatabaseDescriptorTest.java
index f6d4ad4..46522cc 100644
--- a/test/unit/org/apache/cassandra/config/DatabaseDescriptorTest.java
+++ b/test/unit/org/apache/cassandra/config/DatabaseDescriptorTest.java
@@ -18,9 +18,17 @@
*/
package org.apache.cassandra.config;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.util.Enumeration;
+
+import junit.framework.Assert;
+
+import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
-
import org.apache.cassandra.OrderedJUnit4ClassRunner;
import org.apache.cassandra.SchemaLoader;
import org.apache.cassandra.db.Keyspace;
@@ -126,4 +134,133 @@ public class DatabaseDescriptorTest
return testConfig;
}
}
+
+ static NetworkInterface suitableInterface = null;
+ static boolean hasIPv4andIPv6 = false;
+
+ /*
+ * Server only accepts interfaces by name if they have a single address
+ * OS X seems to always have an ipv4 and ipv6 address on all interfaces which means some tests fail
+ * if not checked for and skipped
+ */
+ @BeforeClass
+ public static void selectSuitableInterface() throws Exception {
+ Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
+ while(interfaces.hasMoreElements()) {
+ NetworkInterface intf = interfaces.nextElement();
+
+ System.out.println("Evaluating " + intf.getName());
+
+ if (intf.isLoopback()) {
+ suitableInterface = intf;
+
+ boolean hasIPv4 = false;
+ boolean hasIPv6 = false;
+ Enumeration<InetAddress> addresses = suitableInterface.getInetAddresses();
+ while (addresses.hasMoreElements()) {
+ if (addresses.nextElement().getClass() == Inet6Address.class)
+ hasIPv6 = true;
+ else
+ hasIPv4 = true;
+ }
+ hasIPv4andIPv6 = hasIPv4 && hasIPv6;
+ return;
+ }
+ }
+ }
+
+ @Test
+ public void testRpcInterface() throws Exception
+ {
+ Config testConfig = DatabaseDescriptor.loadConfig();
+ testConfig.rpc_interface = suitableInterface.getName();
+ testConfig.rpc_address = null;
+ DatabaseDescriptor.applyAddressConfig(testConfig);
+
+ /*
+ * Confirm ability to select between IPv4 and IPv6
+ */
+ if (hasIPv4andIPv6)
+ {
+ testConfig = DatabaseDescriptor.loadConfig();
+ testConfig.rpc_interface = suitableInterface.getName();
+ testConfig.rpc_address = null;
+ testConfig.rpc_interface_prefer_ipv6 = true;
+ DatabaseDescriptor.applyAddressConfig(testConfig);
+
+ assertEquals(DatabaseDescriptor.getRpcAddress().getClass(), Inet6Address.class);
+
+ testConfig = DatabaseDescriptor.loadConfig();
+ testConfig.rpc_interface = suitableInterface.getName();
+ testConfig.rpc_address = null;
+ testConfig.rpc_interface_prefer_ipv6 = false;
+ DatabaseDescriptor.applyAddressConfig(testConfig);
+
+ assertEquals(DatabaseDescriptor.getRpcAddress().getClass(), Inet4Address.class);
+ }
+ else
+ {
+ /*
+ * Confirm first address of interface is selected
+ */
+ assertEquals(DatabaseDescriptor.getRpcAddress(), suitableInterface.getInetAddresses().nextElement());
+ }
+ }
+
+ @Test
+ public void testListenInterface() throws Exception
+ {
+ Config testConfig = DatabaseDescriptor.loadConfig();
+ testConfig.listen_interface = suitableInterface.getName();
+ testConfig.listen_address = null;
+ DatabaseDescriptor.applyAddressConfig(testConfig);
+
+ /*
+ * Confirm ability to select between IPv4 and IPv6
+ */
+ if (hasIPv4andIPv6)
+ {
+ testConfig = DatabaseDescriptor.loadConfig();
+ testConfig.listen_interface = suitableInterface.getName();
+ testConfig.listen_address = null;
+ testConfig.listen_interface_prefer_ipv6 = true;
+ DatabaseDescriptor.applyAddressConfig(testConfig);
+
+ assertEquals(DatabaseDescriptor.getListenAddress().getClass(), Inet6Address.class);
+
+ testConfig = DatabaseDescriptor.loadConfig();
+ testConfig.listen_interface = suitableInterface.getName();
+ testConfig.listen_address = null;
+ testConfig.listen_interface_prefer_ipv6 = false;
+ DatabaseDescriptor.applyAddressConfig(testConfig);
+
+ assertEquals(DatabaseDescriptor.getListenAddress().getClass(), Inet4Address.class);
+ }
+ else
+ {
+ /*
+ * Confirm first address of interface is selected
+ */
+ assertEquals(DatabaseDescriptor.getRpcAddress(), suitableInterface.getInetAddresses().nextElement());
+ }
+ }
+
+ @Test
+ public void testListenAddress() throws Exception
+ {
+ Config testConfig = DatabaseDescriptor.loadConfig();
+ testConfig.listen_address = suitableInterface.getInterfaceAddresses().get(0).getAddress().getHostAddress();
+ testConfig.listen_interface = null;
+ DatabaseDescriptor.applyAddressConfig(testConfig);
+ }
+
+ @Test
+ public void testRpcAddress() throws Exception
+ {
+ Config testConfig = DatabaseDescriptor.loadConfig();
+ testConfig.rpc_address = suitableInterface.getInterfaceAddresses().get(0).getAddress().getHostAddress();
+ testConfig.rpc_interface = null;
+ DatabaseDescriptor.applyAddressConfig(testConfig);
+
+ }
}
[2/3] cassandra git commit: DatabaseDescriptor throws NPE when
rpc_interface is used
Posted by sn...@apache.org.
DatabaseDescriptor throws NPE when rpc_interface is used
patch by Ariel Weisberg; reviewed by Carl Yeksigian for CASSANDRA-8839
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/89cdfd8e
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/89cdfd8e
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/89cdfd8e
Branch: refs/heads/trunk
Commit: 89cdfd8e075d8883d776d7f881735f1c25e3cb54
Parents: c0f159b
Author: Ariel Weisberg <ar...@weisberg.ws>
Authored: Tue Mar 17 19:27:54 2015 +0100
Committer: Robert Stupp <sn...@snazy.de>
Committed: Tue Mar 17 19:27:54 2015 +0100
----------------------------------------------------------------------
CHANGES.txt | 1 +
conf/cassandra.yaml | 12 ++
.../org/apache/cassandra/config/Config.java | 6 +-
.../cassandra/config/DatabaseDescriptor.java | 205 +++++++++++--------
.../config/YamlConfigurationLoader.java | 16 +-
.../config/DatabaseDescriptorTest.java | 139 ++++++++++++-
6 files changed, 277 insertions(+), 102 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cassandra/blob/89cdfd8e/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 7b8e0ad..30bf698 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
2.1.4
+ * DatabaseDescriptor throws NPE when rpc_interface is used (CASSANDRA-8839)
* Don't check if an sstable is live for offline compactions (CASSANDRA-8841)
* Don't set clientMode in SSTableLoader (CASSANDRA-8238)
* Fix SSTableRewriter with disabled early open (CASSANDRA-8535)
http://git-wip-us.apache.org/repos/asf/cassandra/blob/89cdfd8e/conf/cassandra.yaml
----------------------------------------------------------------------
diff --git a/conf/cassandra.yaml b/conf/cassandra.yaml
index cea12b3..2b43ba7 100644
--- a/conf/cassandra.yaml
+++ b/conf/cassandra.yaml
@@ -370,8 +370,14 @@ ssl_storage_port: 7001
# address associated with the hostname (it might not be).
#
# Setting listen_address to 0.0.0.0 is always wrong.
+#
+# If you choose to specify the interface by name and the interface has an ipv4 and an ipv6 address
+# you can specify which should be chosen using listen_interface_prefer_ipv6. If false the first ipv4
+# address will be used. If true the first ipv6 address will be used. Defaults to false preferring
+# ipv4. If there is only one address it will be selected regardless of ipv4/ipv6.
listen_address: localhost
# listen_interface: eth0
+# listen_interface_prefer_ipv6: false
# Address to broadcast to other Cassandra nodes
# Leaving this blank will set it to the same value as listen_address
@@ -422,8 +428,14 @@ start_rpc: true
# set broadcast_rpc_address to a value other than 0.0.0.0.
#
# For security reasons, you should not expose this port to the internet. Firewall it if needed.
+#
+# If you choose to specify the interface by name and the interface has an ipv4 and an ipv6 address
+# you can specify which should be chosen using rpc_interface_prefer_ipv6. If false the first ipv4
+# address will be used. If true the first ipv6 address will be used. Defaults to false preferring
+# ipv4. If there is only one address it will be selected regardless of ipv4/ipv6.
rpc_address: localhost
# rpc_interface: eth1
+# rpc_interface_prefer_ipv6: false
# port for Thrift to listen for clients on
rpc_port: 9160
http://git-wip-us.apache.org/repos/asf/cassandra/blob/89cdfd8e/src/java/org/apache/cassandra/config/Config.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/config/Config.java b/src/java/org/apache/cassandra/config/Config.java
index ccd4467..fbbd1dd 100644
--- a/src/java/org/apache/cassandra/config/Config.java
+++ b/src/java/org/apache/cassandra/config/Config.java
@@ -34,7 +34,7 @@ import org.apache.cassandra.utils.FBUtilities;
/**
* A class that contains configuration properties for the cassandra node it runs within.
- *
+ *
* Properties declared as volatile can be mutated via JMX.
*/
public class Config
@@ -101,12 +101,14 @@ public class Config
public Integer ssl_storage_port = 7001;
public String listen_address;
public String listen_interface;
+ public Boolean listen_interface_prefer_ipv6 = false;
public String broadcast_address;
public String internode_authenticator;
public Boolean start_rpc = true;
public String rpc_address;
public String rpc_interface;
+ public Boolean rpc_interface_prefer_ipv6 = false;
public String broadcast_rpc_address;
public Integer rpc_port = 9160;
public Integer rpc_listen_backlog = 50;
@@ -155,7 +157,7 @@ public class Config
public Double commitlog_sync_batch_window_in_ms;
public Integer commitlog_sync_period_in_ms;
public int commitlog_segment_size_in_mb = 32;
-
+
@Deprecated
public int commitlog_periodic_queue_size = -1;
http://git-wip-us.apache.org/repos/asf/cassandra/blob/89cdfd8e/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
index 4426f20..65cec9c 100644
--- a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
+++ b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
@@ -20,6 +20,8 @@ package org.apache.cassandra.config;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
@@ -38,6 +40,7 @@ import java.util.UUID;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableSet;
import com.google.common.primitives.Longs;
+
import org.apache.cassandra.thrift.ThriftServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -158,7 +161,7 @@ public class DatabaseDescriptor
return loader.loadConfig();
}
- private static InetAddress getNetworkInterfaceAddress(String intf, String configName) throws ConfigurationException
+ private static InetAddress getNetworkInterfaceAddress(String intf, String configName, boolean preferIPv6) throws ConfigurationException
{
try
{
@@ -168,9 +171,18 @@ public class DatabaseDescriptor
Enumeration<InetAddress> addrs = ni.getInetAddresses();
if (!addrs.hasMoreElements())
throw new ConfigurationException("Configured " + configName + " \"" + intf + "\" was found, but had no addresses");
- InetAddress retval = listenAddress = addrs.nextElement();
- if (addrs.hasMoreElements())
- throw new ConfigurationException("Configured " + configName + " \"" + intf + "\" can't have more than one address");
+
+ /*
+ * Try to return the first address of the preferred type, otherwise return the first address
+ */
+ InetAddress retval = null;
+ while (addrs.hasMoreElements())
+ {
+ InetAddress temp = addrs.nextElement();
+ if (preferIPv6 && temp.getClass() == Inet6Address.class) return temp;
+ if (!preferIPv6 && temp.getClass() == Inet4Address.class) return temp;
+ if (retval == null) retval = temp;
+ }
return retval;
}
catch (SocketException e)
@@ -179,6 +191,103 @@ public class DatabaseDescriptor
}
}
+ @VisibleForTesting
+ static void applyAddressConfig(Config config) throws ConfigurationException
+ {
+ listenAddress = null;
+ rpcAddress = null;
+ broadcastAddress = null;
+ broadcastRpcAddress = null;
+
+ /* Local IP, hostname or interface to bind services to */
+ if (config.listen_address != null && config.listen_interface != null)
+ {
+ throw new ConfigurationException("Set listen_address OR listen_interface, not both");
+ }
+ else if (config.listen_address != null)
+ {
+ try
+ {
+ listenAddress = InetAddress.getByName(config.listen_address);
+ }
+ catch (UnknownHostException e)
+ {
+ throw new ConfigurationException("Unknown listen_address '" + config.listen_address + "'");
+ }
+
+ if (listenAddress.isAnyLocalAddress())
+ throw new ConfigurationException("listen_address cannot be a wildcard address (" + config.listen_address + ")!");
+ }
+ else if (config.listen_interface != null)
+ {
+ listenAddress = getNetworkInterfaceAddress(config.listen_interface, "listen_interface", config.listen_interface_prefer_ipv6);
+ }
+
+ /* Gossip Address to broadcast */
+ if (config.broadcast_address != null)
+ {
+ try
+ {
+ broadcastAddress = InetAddress.getByName(config.broadcast_address);
+ }
+ catch (UnknownHostException e)
+ {
+ throw new ConfigurationException("Unknown broadcast_address '" + config.broadcast_address + "'");
+ }
+
+ if (broadcastAddress.isAnyLocalAddress())
+ throw new ConfigurationException("broadcast_address cannot be a wildcard address (" + config.broadcast_address + ")!");
+ }
+
+ /* Local IP, hostname or interface to bind RPC server to */
+ if (config.rpc_address != null && config.rpc_interface != null)
+ {
+ throw new ConfigurationException("Set rpc_address OR rpc_interface, not both");
+ }
+ else if (config.rpc_address != null)
+ {
+ try
+ {
+ rpcAddress = InetAddress.getByName(config.rpc_address);
+ }
+ catch (UnknownHostException e)
+ {
+ throw new ConfigurationException("Unknown host in rpc_address " + config.rpc_address);
+ }
+ }
+ else if (config.rpc_interface != null)
+ {
+ rpcAddress = getNetworkInterfaceAddress(config.rpc_interface, "rpc_interface", config.rpc_interface_prefer_ipv6);
+ }
+ else
+ {
+ rpcAddress = FBUtilities.getLocalAddress();
+ }
+
+ /* RPC address to broadcast */
+ if (config.broadcast_rpc_address != null)
+ {
+ try
+ {
+ broadcastRpcAddress = InetAddress.getByName(config.broadcast_rpc_address);
+ }
+ catch (UnknownHostException e)
+ {
+ throw new ConfigurationException("Unknown broadcast_rpc_address '" + config.broadcast_rpc_address + "'");
+ }
+
+ if (broadcastRpcAddress.isAnyLocalAddress())
+ throw new ConfigurationException("broadcast_rpc_address cannot be a wildcard address (" + config.broadcast_rpc_address + ")!");
+ }
+ else
+ {
+ if (rpcAddress.isAnyLocalAddress())
+ throw new ConfigurationException("If rpc_address is set to a wildcard address (" + config.rpc_address + "), then " +
+ "you must set broadcast_rpc_address to a value other than " + config.rpc_address);
+ broadcastRpcAddress = rpcAddress;
+ }
+ }
+
private static void applyConfig(Config config) throws ConfigurationException
{
conf = config;
@@ -326,93 +435,7 @@ public class DatabaseDescriptor
else
logger.info("Global memtable off-heap threshold is enabled at {}MB", conf.memtable_offheap_space_in_mb);
- /* Local IP, hostname or interface to bind services to */
- if (conf.listen_address != null && conf.listen_interface != null)
- {
- throw new ConfigurationException("Set listen_address OR listen_interface, not both");
- }
- else if (conf.listen_address != null)
- {
- try
- {
- listenAddress = InetAddress.getByName(conf.listen_address);
- }
- catch (UnknownHostException e)
- {
- throw new ConfigurationException("Unknown listen_address '" + conf.listen_address + "'");
- }
-
- if (listenAddress.isAnyLocalAddress())
- throw new ConfigurationException("listen_address cannot be a wildcard address (" + conf.listen_address + ")!");
- }
- else if (conf.listen_interface != null)
- {
- listenAddress = getNetworkInterfaceAddress(conf.listen_interface, "listen_interface");
- }
-
- /* Gossip Address to broadcast */
- if (conf.broadcast_address != null)
- {
- try
- {
- broadcastAddress = InetAddress.getByName(conf.broadcast_address);
- }
- catch (UnknownHostException e)
- {
- throw new ConfigurationException("Unknown broadcast_address '" + conf.broadcast_address + "'");
- }
-
- if (broadcastAddress.isAnyLocalAddress())
- throw new ConfigurationException("broadcast_address cannot be a wildcard address (" + conf.broadcast_address + ")!");
- }
-
- /* Local IP, hostname or interface to bind RPC server to */
- if (conf.rpc_address != null && conf.rpc_interface != null)
- {
- throw new ConfigurationException("Set rpc_address OR rpc_interface, not both");
- }
- else if (conf.rpc_address != null)
- {
- try
- {
- rpcAddress = InetAddress.getByName(conf.rpc_address);
- }
- catch (UnknownHostException e)
- {
- throw new ConfigurationException("Unknown host in rpc_address " + conf.rpc_address);
- }
- }
- else if (conf.rpc_interface != null)
- {
- listenAddress = getNetworkInterfaceAddress(conf.rpc_interface, "rpc_interface");
- }
- else
- {
- rpcAddress = FBUtilities.getLocalAddress();
- }
-
- /* RPC address to broadcast */
- if (conf.broadcast_rpc_address != null)
- {
- try
- {
- broadcastRpcAddress = InetAddress.getByName(conf.broadcast_rpc_address);
- }
- catch (UnknownHostException e)
- {
- throw new ConfigurationException("Unknown broadcast_rpc_address '" + conf.broadcast_rpc_address + "'");
- }
-
- if (broadcastRpcAddress.isAnyLocalAddress())
- throw new ConfigurationException("broadcast_rpc_address cannot be a wildcard address (" + conf.broadcast_rpc_address + ")!");
- }
- else
- {
- if (rpcAddress.isAnyLocalAddress())
- throw new ConfigurationException("If rpc_address is set to a wildcard address (" + conf.rpc_address + "), then " +
- "you must set broadcast_rpc_address to a value other than " + conf.rpc_address);
- broadcastRpcAddress = rpcAddress;
- }
+ applyAddressConfig(config);
if (conf.thrift_framed_transport_size_in_mb <= 0)
throw new ConfigurationException("thrift_framed_transport_size_in_mb must be positive");
http://git-wip-us.apache.org/repos/asf/cassandra/blob/89cdfd8e/src/java/org/apache/cassandra/config/YamlConfigurationLoader.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/config/YamlConfigurationLoader.java b/src/java/org/apache/cassandra/config/YamlConfigurationLoader.java
index e222046..0061926 100644
--- a/src/java/org/apache/cassandra/config/YamlConfigurationLoader.java
+++ b/src/java/org/apache/cassandra/config/YamlConfigurationLoader.java
@@ -50,7 +50,7 @@ public class YamlConfigurationLoader implements ConfigurationLoader
/**
* Inspect the classpath to find storage configuration file
*/
- private URL getStorageConfigURL() throws ConfigurationException
+ static URL getStorageConfigURL() throws ConfigurationException
{
String configUrl = System.getProperty("cassandra.config");
if (configUrl == null)
@@ -100,7 +100,7 @@ public class YamlConfigurationLoader implements ConfigurationLoader
// getStorageConfigURL should have ruled this out
throw new AssertionError(e);
}
-
+
logConfig(configBytes);
org.yaml.snakeyaml.constructor.Constructor constructor = new org.yaml.snakeyaml.constructor.Constructor(Config.class);
@@ -134,16 +134,16 @@ public class YamlConfigurationLoader implements ConfigurationLoader
}
logger.info("Node configuration:[" + Joiner.on("; ").join(configMap.entrySet()) + "]");
}
-
- private static class MissingPropertiesChecker extends PropertyUtils
+
+ private static class MissingPropertiesChecker extends PropertyUtils
{
private final Set<String> missingProperties = new HashSet<>();
-
+
public MissingPropertiesChecker()
{
setSkipMissingProperties(true);
}
-
+
@Override
public Property getProperty(Class<? extends Object> type, String name) throws IntrospectionException
{
@@ -154,10 +154,10 @@ public class YamlConfigurationLoader implements ConfigurationLoader
}
return result;
}
-
+
public void check() throws ConfigurationException
{
- if (!missingProperties.isEmpty())
+ if (!missingProperties.isEmpty())
{
throw new ConfigurationException("Invalid yaml. Please remove properties " + missingProperties + " from your cassandra.yaml");
}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/89cdfd8e/test/unit/org/apache/cassandra/config/DatabaseDescriptorTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/config/DatabaseDescriptorTest.java b/test/unit/org/apache/cassandra/config/DatabaseDescriptorTest.java
index f6d4ad4..46522cc 100644
--- a/test/unit/org/apache/cassandra/config/DatabaseDescriptorTest.java
+++ b/test/unit/org/apache/cassandra/config/DatabaseDescriptorTest.java
@@ -18,9 +18,17 @@
*/
package org.apache.cassandra.config;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.util.Enumeration;
+
+import junit.framework.Assert;
+
+import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
-
import org.apache.cassandra.OrderedJUnit4ClassRunner;
import org.apache.cassandra.SchemaLoader;
import org.apache.cassandra.db.Keyspace;
@@ -126,4 +134,133 @@ public class DatabaseDescriptorTest
return testConfig;
}
}
+
+ static NetworkInterface suitableInterface = null;
+ static boolean hasIPv4andIPv6 = false;
+
+ /*
+ * Server only accepts interfaces by name if they have a single address
+ * OS X seems to always have an ipv4 and ipv6 address on all interfaces which means some tests fail
+ * if not checked for and skipped
+ */
+ @BeforeClass
+ public static void selectSuitableInterface() throws Exception {
+ Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
+ while(interfaces.hasMoreElements()) {
+ NetworkInterface intf = interfaces.nextElement();
+
+ System.out.println("Evaluating " + intf.getName());
+
+ if (intf.isLoopback()) {
+ suitableInterface = intf;
+
+ boolean hasIPv4 = false;
+ boolean hasIPv6 = false;
+ Enumeration<InetAddress> addresses = suitableInterface.getInetAddresses();
+ while (addresses.hasMoreElements()) {
+ if (addresses.nextElement().getClass() == Inet6Address.class)
+ hasIPv6 = true;
+ else
+ hasIPv4 = true;
+ }
+ hasIPv4andIPv6 = hasIPv4 && hasIPv6;
+ return;
+ }
+ }
+ }
+
+ @Test
+ public void testRpcInterface() throws Exception
+ {
+ Config testConfig = DatabaseDescriptor.loadConfig();
+ testConfig.rpc_interface = suitableInterface.getName();
+ testConfig.rpc_address = null;
+ DatabaseDescriptor.applyAddressConfig(testConfig);
+
+ /*
+ * Confirm ability to select between IPv4 and IPv6
+ */
+ if (hasIPv4andIPv6)
+ {
+ testConfig = DatabaseDescriptor.loadConfig();
+ testConfig.rpc_interface = suitableInterface.getName();
+ testConfig.rpc_address = null;
+ testConfig.rpc_interface_prefer_ipv6 = true;
+ DatabaseDescriptor.applyAddressConfig(testConfig);
+
+ assertEquals(DatabaseDescriptor.getRpcAddress().getClass(), Inet6Address.class);
+
+ testConfig = DatabaseDescriptor.loadConfig();
+ testConfig.rpc_interface = suitableInterface.getName();
+ testConfig.rpc_address = null;
+ testConfig.rpc_interface_prefer_ipv6 = false;
+ DatabaseDescriptor.applyAddressConfig(testConfig);
+
+ assertEquals(DatabaseDescriptor.getRpcAddress().getClass(), Inet4Address.class);
+ }
+ else
+ {
+ /*
+ * Confirm first address of interface is selected
+ */
+ assertEquals(DatabaseDescriptor.getRpcAddress(), suitableInterface.getInetAddresses().nextElement());
+ }
+ }
+
+ @Test
+ public void testListenInterface() throws Exception
+ {
+ Config testConfig = DatabaseDescriptor.loadConfig();
+ testConfig.listen_interface = suitableInterface.getName();
+ testConfig.listen_address = null;
+ DatabaseDescriptor.applyAddressConfig(testConfig);
+
+ /*
+ * Confirm ability to select between IPv4 and IPv6
+ */
+ if (hasIPv4andIPv6)
+ {
+ testConfig = DatabaseDescriptor.loadConfig();
+ testConfig.listen_interface = suitableInterface.getName();
+ testConfig.listen_address = null;
+ testConfig.listen_interface_prefer_ipv6 = true;
+ DatabaseDescriptor.applyAddressConfig(testConfig);
+
+ assertEquals(DatabaseDescriptor.getListenAddress().getClass(), Inet6Address.class);
+
+ testConfig = DatabaseDescriptor.loadConfig();
+ testConfig.listen_interface = suitableInterface.getName();
+ testConfig.listen_address = null;
+ testConfig.listen_interface_prefer_ipv6 = false;
+ DatabaseDescriptor.applyAddressConfig(testConfig);
+
+ assertEquals(DatabaseDescriptor.getListenAddress().getClass(), Inet4Address.class);
+ }
+ else
+ {
+ /*
+ * Confirm first address of interface is selected
+ */
+ assertEquals(DatabaseDescriptor.getRpcAddress(), suitableInterface.getInetAddresses().nextElement());
+ }
+ }
+
+ @Test
+ public void testListenAddress() throws Exception
+ {
+ Config testConfig = DatabaseDescriptor.loadConfig();
+ testConfig.listen_address = suitableInterface.getInterfaceAddresses().get(0).getAddress().getHostAddress();
+ testConfig.listen_interface = null;
+ DatabaseDescriptor.applyAddressConfig(testConfig);
+ }
+
+ @Test
+ public void testRpcAddress() throws Exception
+ {
+ Config testConfig = DatabaseDescriptor.loadConfig();
+ testConfig.rpc_address = suitableInterface.getInterfaceAddresses().get(0).getAddress().getHostAddress();
+ testConfig.rpc_interface = null;
+ DatabaseDescriptor.applyAddressConfig(testConfig);
+
+ }
}
[3/3] cassandra git commit: Merge branch 'cassandra-2.1' into trunk
Posted by sn...@apache.org.
Merge branch 'cassandra-2.1' into trunk
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/8d570fa7
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/8d570fa7
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/8d570fa7
Branch: refs/heads/trunk
Commit: 8d570fa7992f8eaae55e8c13c57e6e84491062ee
Parents: ac9ccfd 89cdfd8
Author: Ariel Weisberg <ar...@weisberg.ws>
Authored: Tue Mar 17 19:31:54 2015 +0100
Committer: Robert Stupp <sn...@snazy.de>
Committed: Tue Mar 17 19:31:54 2015 +0100
----------------------------------------------------------------------
CHANGES.txt | 1 +
conf/cassandra.yaml | 12 ++
.../org/apache/cassandra/config/Config.java | 6 +-
.../cassandra/config/DatabaseDescriptor.java | 202 ++++++++++---------
.../config/YamlConfigurationLoader.java | 16 +-
.../config/DatabaseDescriptorTest.java | 139 ++++++++++++-
6 files changed, 274 insertions(+), 102 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cassandra/blob/8d570fa7/CHANGES.txt
----------------------------------------------------------------------
diff --cc CHANGES.txt
index be57f1b,30bf698..f813496
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@@ -1,76 -1,5 +1,77 @@@
+3.0
+ * Add WriteFailureException to native protocol, notify coordinator of
+ write failures (CASSANDRA-8592)
+ * Convert SequentialWriter to nio (CASSANDRA-8709)
+ * Add role based access control (CASSANDRA-7653, 8650, 7216, 8760, 8849, 8761, 8850)
+ * Record client ip address in tracing sessions (CASSANDRA-8162)
+ * Indicate partition key columns in response metadata for prepared
+ statements (CASSANDRA-7660)
+ * Merge UUIDType and TimeUUIDType parse logic (CASSANDRA-8759)
+ * Avoid memory allocation when searching index summary (CASSANDRA-8793)
+ * Optimise (Time)?UUIDType Comparisons (CASSANDRA-8730)
+ * Make CRC32Ex into a separate maven dependency (CASSANDRA-8836)
+ * Use preloaded jemalloc w/ Unsafe (CASSANDRA-8714)
+ * Avoid accessing partitioner through StorageProxy (CASSANDRA-8244, 8268)
+ * Upgrade Metrics library and remove depricated metrics (CASSANDRA-5657)
+ * Serializing Row cache alternative, fully off heap (CASSANDRA-7438)
+ * Duplicate rows returned when in clause has repeated values (CASSANDRA-6707)
+ * Make CassandraException unchecked, extend RuntimeException (CASSANDRA-8560)
+ * Support direct buffer decompression for reads (CASSANDRA-8464)
+ * DirectByteBuffer compatible LZ4 methods (CASSANDRA-7039)
+ * Group sstables for anticompaction correctly (CASSANDRA-8578)
+ * Add ReadFailureException to native protocol, respond
+ immediately when replicas encounter errors while handling
+ a read request (CASSANDRA-7886)
+ * Switch CommitLogSegment from RandomAccessFile to nio (CASSANDRA-8308)
+ * Allow mixing token and partition key restrictions (CASSANDRA-7016)
+ * Support index key/value entries on map collections (CASSANDRA-8473)
+ * Modernize schema tables (CASSANDRA-8261)
+ * Support for user-defined aggregation functions (CASSANDRA-8053)
+ * Fix NPE in SelectStatement with empty IN values (CASSANDRA-8419)
+ * Refactor SelectStatement, return IN results in natural order instead
+ of IN value list order and ignore duplicate values in partition key IN restrictions (CASSANDRA-7981)
+ * Support UDTs, tuples, and collections in user-defined
+ functions (CASSANDRA-7563)
+ * Fix aggregate fn results on empty selection, result column name,
+ and cqlsh parsing (CASSANDRA-8229)
+ * Mark sstables as repaired after full repair (CASSANDRA-7586)
+ * Extend Descriptor to include a format value and refactor reader/writer
+ APIs (CASSANDRA-7443)
+ * Integrate JMH for microbenchmarks (CASSANDRA-8151)
+ * Keep sstable levels when bootstrapping (CASSANDRA-7460)
+ * Add Sigar library and perform basic OS settings check on startup (CASSANDRA-7838)
+ * Support for aggregation functions (CASSANDRA-4914)
+ * Remove cassandra-cli (CASSANDRA-7920)
+ * Accept dollar quoted strings in CQL (CASSANDRA-7769)
+ * Make assassinate a first class command (CASSANDRA-7935)
+ * Support IN clause on any partition key column (CASSANDRA-7855)
+ * Support IN clause on any clustering column (CASSANDRA-4762)
+ * Improve compaction logging (CASSANDRA-7818)
+ * Remove YamlFileNetworkTopologySnitch (CASSANDRA-7917)
+ * Do anticompaction in groups (CASSANDRA-6851)
+ * Support user-defined functions (CASSANDRA-7395, 7526, 7562, 7740, 7781, 7929,
+ 7924, 7812, 8063, 7813, 7708)
+ * Permit configurable timestamps with cassandra-stress (CASSANDRA-7416)
+ * Move sstable RandomAccessReader to nio2, which allows using the
+ FILE_SHARE_DELETE flag on Windows (CASSANDRA-4050)
+ * Remove CQL2 (CASSANDRA-5918)
+ * Add Thrift get_multi_slice call (CASSANDRA-6757)
+ * Optimize fetching multiple cells by name (CASSANDRA-6933)
+ * Allow compilation in java 8 (CASSANDRA-7028)
+ * Make incremental repair default (CASSANDRA-7250)
+ * Enable code coverage thru JaCoCo (CASSANDRA-7226)
+ * Switch external naming of 'column families' to 'tables' (CASSANDRA-4369)
+ * Shorten SSTable path (CASSANDRA-6962)
+ * Use unsafe mutations for most unit tests (CASSANDRA-6969)
+ * Fix race condition during calculation of pending ranges (CASSANDRA-7390)
+ * Fail on very large batch sizes (CASSANDRA-8011)
+ * Improve concurrency of repair (CASSANDRA-6455, 8208)
+ * Select optimal CRC32 implementation at runtime (CASSANDRA-8614)
+ * Evaluate MurmurHash of Token once per query (CASSANDRA-7096)
+ * Generalize progress reporting (CASSANDRA-8901)
+
2.1.4
+ * DatabaseDescriptor throws NPE when rpc_interface is used (CASSANDRA-8839)
* Don't check if an sstable is live for offline compactions (CASSANDRA-8841)
* Don't set clientMode in SSTableLoader (CASSANDRA-8238)
* Fix SSTableRewriter with disabled early open (CASSANDRA-8535)
http://git-wip-us.apache.org/repos/asf/cassandra/blob/8d570fa7/conf/cassandra.yaml
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cassandra/blob/8d570fa7/src/java/org/apache/cassandra/config/Config.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cassandra/blob/8d570fa7/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/config/DatabaseDescriptor.java
index 35ce728,65cec9c..fa88de8
--- a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
+++ b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
@@@ -131,13 -167,22 +131,22 @@@ public class DatabaseDescripto
{
NetworkInterface ni = NetworkInterface.getByName(intf);
if (ni == null)
- throw new ConfigurationException("Configured " + configName + " \"" + intf + "\" could not be found");
+ throw new ConfigurationException("Configured " + configName + " \"" + intf + "\" could not be found", false);
Enumeration<InetAddress> addrs = ni.getInetAddresses();
if (!addrs.hasMoreElements())
- throw new ConfigurationException("Configured " + configName + " \"" + intf + "\" was found, but had no addresses");
+ throw new ConfigurationException("Configured " + configName + " \"" + intf + "\" was found, but had no addresses", false);
- InetAddress retval = listenAddress = addrs.nextElement();
- if (addrs.hasMoreElements())
- throw new ConfigurationException("Configured " + configName + " \"" + intf + "\" can't have more than one address", false);
+
+ /*
+ * Try to return the first address of the preferred type, otherwise return the first address
+ */
+ InetAddress retval = null;
+ while (addrs.hasMoreElements())
+ {
+ InetAddress temp = addrs.nextElement();
- if (preferIPv6 && temp.getClass() == Inet6Address.class) return temp;
- if (!preferIPv6 && temp.getClass() == Inet4Address.class) return temp;
++ if (preferIPv6 && temp instanceof Inet6Address) return temp;
++ if (!preferIPv6 && temp instanceof Inet4Address) return temp;
+ if (retval == null) retval = temp;
+ }
return retval;
}
catch (SocketException e)
@@@ -146,6 -191,103 +155,103 @@@
}
}
+ @VisibleForTesting
+ static void applyAddressConfig(Config config) throws ConfigurationException
+ {
+ listenAddress = null;
+ rpcAddress = null;
+ broadcastAddress = null;
+ broadcastRpcAddress = null;
+
+ /* Local IP, hostname or interface to bind services to */
+ if (config.listen_address != null && config.listen_interface != null)
+ {
- throw new ConfigurationException("Set listen_address OR listen_interface, not both");
++ throw new ConfigurationException("Set listen_address OR listen_interface, not both", false);
+ }
+ else if (config.listen_address != null)
+ {
+ try
+ {
+ listenAddress = InetAddress.getByName(config.listen_address);
+ }
+ catch (UnknownHostException e)
+ {
- throw new ConfigurationException("Unknown listen_address '" + config.listen_address + "'");
++ throw new ConfigurationException("Unknown listen_address '" + config.listen_address + "'", false);
+ }
+
+ if (listenAddress.isAnyLocalAddress())
- throw new ConfigurationException("listen_address cannot be a wildcard address (" + config.listen_address + ")!");
++ throw new ConfigurationException("listen_address cannot be a wildcard address (" + config.listen_address + ")!", false);
+ }
+ else if (config.listen_interface != null)
+ {
+ listenAddress = getNetworkInterfaceAddress(config.listen_interface, "listen_interface", config.listen_interface_prefer_ipv6);
+ }
+
+ /* Gossip Address to broadcast */
+ if (config.broadcast_address != null)
+ {
+ try
+ {
+ broadcastAddress = InetAddress.getByName(config.broadcast_address);
+ }
+ catch (UnknownHostException e)
+ {
- throw new ConfigurationException("Unknown broadcast_address '" + config.broadcast_address + "'");
++ throw new ConfigurationException("Unknown broadcast_address '" + config.broadcast_address + "'", false);
+ }
+
+ if (broadcastAddress.isAnyLocalAddress())
- throw new ConfigurationException("broadcast_address cannot be a wildcard address (" + config.broadcast_address + ")!");
++ throw new ConfigurationException("broadcast_address cannot be a wildcard address (" + config.broadcast_address + ")!", false);
+ }
+
+ /* Local IP, hostname or interface to bind RPC server to */
+ if (config.rpc_address != null && config.rpc_interface != null)
+ {
- throw new ConfigurationException("Set rpc_address OR rpc_interface, not both");
++ throw new ConfigurationException("Set rpc_address OR rpc_interface, not both", false);
+ }
+ else if (config.rpc_address != null)
+ {
+ try
+ {
+ rpcAddress = InetAddress.getByName(config.rpc_address);
+ }
+ catch (UnknownHostException e)
+ {
- throw new ConfigurationException("Unknown host in rpc_address " + config.rpc_address);
++ throw new ConfigurationException("Unknown host in rpc_address " + config.rpc_address, false);
+ }
+ }
+ else if (config.rpc_interface != null)
+ {
+ rpcAddress = getNetworkInterfaceAddress(config.rpc_interface, "rpc_interface", config.rpc_interface_prefer_ipv6);
+ }
+ else
+ {
+ rpcAddress = FBUtilities.getLocalAddress();
+ }
+
+ /* RPC address to broadcast */
+ if (config.broadcast_rpc_address != null)
+ {
+ try
+ {
+ broadcastRpcAddress = InetAddress.getByName(config.broadcast_rpc_address);
+ }
+ catch (UnknownHostException e)
+ {
- throw new ConfigurationException("Unknown broadcast_rpc_address '" + config.broadcast_rpc_address + "'");
++ throw new ConfigurationException("Unknown broadcast_rpc_address '" + config.broadcast_rpc_address + "'", false);
+ }
+
+ if (broadcastRpcAddress.isAnyLocalAddress())
- throw new ConfigurationException("broadcast_rpc_address cannot be a wildcard address (" + config.broadcast_rpc_address + ")!");
++ throw new ConfigurationException("broadcast_rpc_address cannot be a wildcard address (" + config.broadcast_rpc_address + ")!", false);
+ }
+ else
+ {
+ if (rpcAddress.isAnyLocalAddress())
+ throw new ConfigurationException("If rpc_address is set to a wildcard address (" + config.rpc_address + "), then " +
- "you must set broadcast_rpc_address to a value other than " + config.rpc_address);
++ "you must set broadcast_rpc_address to a value other than " + config.rpc_address, false);
+ broadcastRpcAddress = rpcAddress;
+ }
+ }
+
private static void applyConfig(Config config) throws ConfigurationException
{
conf = config;
@@@ -300,99 -435,13 +406,13 @@@
else
logger.info("Global memtable off-heap threshold is enabled at {}MB", conf.memtable_offheap_space_in_mb);
- /* Local IP, hostname or interface to bind services to */
- if (conf.listen_address != null && conf.listen_interface != null)
- {
- throw new ConfigurationException("Set listen_address OR listen_interface, not both", false);
- }
- else if (conf.listen_address != null)
- {
- try
- {
- listenAddress = InetAddress.getByName(conf.listen_address);
- }
- catch (UnknownHostException e)
- {
- throw new ConfigurationException("Unknown listen_address '" + conf.listen_address + "'", false);
- }
-
- if (listenAddress.isAnyLocalAddress())
- throw new ConfigurationException("listen_address cannot be a wildcard address (" + conf.listen_address + ")!", false);
- }
- else if (conf.listen_interface != null)
- {
- listenAddress = getNetworkInterfaceAddress(conf.listen_interface, "listen_interface");
- }
-
- /* Gossip Address to broadcast */
- if (conf.broadcast_address != null)
- {
- try
- {
- broadcastAddress = InetAddress.getByName(conf.broadcast_address);
- }
- catch (UnknownHostException e)
- {
- throw new ConfigurationException("Unknown broadcast_address '" + conf.broadcast_address + "'", false);
- }
-
- if (broadcastAddress.isAnyLocalAddress())
- throw new ConfigurationException("broadcast_address cannot be a wildcard address (" + conf.broadcast_address + ")!", false);
- }
-
- /* Local IP, hostname or interface to bind RPC server to */
- if (conf.rpc_address != null && conf.rpc_interface != null)
- {
- throw new ConfigurationException("Set rpc_address OR rpc_interface, not both", false);
- }
- else if (conf.rpc_address != null)
- {
- try
- {
- rpcAddress = InetAddress.getByName(conf.rpc_address);
- }
- catch (UnknownHostException e)
- {
- throw new ConfigurationException("Unknown host in rpc_address " + conf.rpc_address, false);
- }
- }
- else if (conf.rpc_interface != null)
- {
- rpcAddress = getNetworkInterfaceAddress(conf.rpc_interface, "rpc_interface");
- }
- else
- {
- rpcAddress = FBUtilities.getLocalAddress();
- }
-
- /* RPC address to broadcast */
- if (conf.broadcast_rpc_address != null)
- {
- try
- {
- broadcastRpcAddress = InetAddress.getByName(conf.broadcast_rpc_address);
- }
- catch (UnknownHostException e)
- {
- throw new ConfigurationException("Unknown broadcast_rpc_address '" + conf.broadcast_rpc_address + "'", false);
- }
-
- if (broadcastRpcAddress.isAnyLocalAddress())
- throw new ConfigurationException("broadcast_rpc_address cannot be a wildcard address (" + conf.broadcast_rpc_address + ")!", false);
- }
- else
- {
- if (rpcAddress.isAnyLocalAddress())
- throw new ConfigurationException("If rpc_address is set to a wildcard address (" + conf.rpc_address + "), then " +
- "you must set broadcast_rpc_address to a value other than " + conf.rpc_address, false);
- broadcastRpcAddress = rpcAddress;
- }
+ applyAddressConfig(config);
if (conf.thrift_framed_transport_size_in_mb <= 0)
- throw new ConfigurationException("thrift_framed_transport_size_in_mb must be positive");
+ throw new ConfigurationException("thrift_framed_transport_size_in_mb must be positive", false);
if (conf.native_transport_max_frame_size_in_mb <= 0)
- throw new ConfigurationException("native_transport_max_frame_size_in_mb must be positive");
+ throw new ConfigurationException("native_transport_max_frame_size_in_mb must be positive", false);
// fail early instead of OOMing (see CASSANDRA-8116)
if (ThriftServer.HSHA.equals(conf.rpc_server_type) && conf.rpc_max_threads == Integer.MAX_VALUE)
http://git-wip-us.apache.org/repos/asf/cassandra/blob/8d570fa7/src/java/org/apache/cassandra/config/YamlConfigurationLoader.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/config/YamlConfigurationLoader.java
index e8847ba,0061926..8b8d75f
--- a/src/java/org/apache/cassandra/config/YamlConfigurationLoader.java
+++ b/src/java/org/apache/cassandra/config/YamlConfigurationLoader.java
@@@ -100,9 -100,9 +100,9 @@@ public class YamlConfigurationLoader im
// getStorageConfigURL should have ruled this out
throw new AssertionError(e);
}
-
+
logConfig(configBytes);
-
+
org.yaml.snakeyaml.constructor.Constructor constructor = new org.yaml.snakeyaml.constructor.Constructor(Config.class);
TypeDescription seedDesc = new TypeDescription(SeedProviderDef.class);
seedDesc.putMapPropertyType("parameters", String.class, String.class);
@@@ -132,13 -132,13 +132,13 @@@
configMap.put(sensitiveKey, "<REDACTED>");
}
}
- logger.info("Node configuration:[" + Joiner.on("; ").join(configMap.entrySet()) + "]");
+ logger.info("Node configuration:[{}]", Joiner.on("; ").join(configMap.entrySet()));
}
-
- private static class MissingPropertiesChecker extends PropertyUtils
+
+ private static class MissingPropertiesChecker extends PropertyUtils
{
private final Set<String> missingProperties = new HashSet<>();
-
+
public MissingPropertiesChecker()
{
setSkipMissingProperties(true);
http://git-wip-us.apache.org/repos/asf/cassandra/blob/8d570fa7/test/unit/org/apache/cassandra/config/DatabaseDescriptorTest.java
----------------------------------------------------------------------
diff --cc test/unit/org/apache/cassandra/config/DatabaseDescriptorTest.java
index 8ca7a79,46522cc..57c4194
--- a/test/unit/org/apache/cassandra/config/DatabaseDescriptorTest.java
+++ b/test/unit/org/apache/cassandra/config/DatabaseDescriptorTest.java
@@@ -128,4 -134,133 +136,133 @@@ public class DatabaseDescriptorTes
return testConfig;
}
}
+
+ static NetworkInterface suitableInterface = null;
+ static boolean hasIPv4andIPv6 = false;
+
+ /*
+ * Server only accepts interfaces by name if they have a single address
+ * OS X seems to always have an ipv4 and ipv6 address on all interfaces which means some tests fail
+ * if not checked for and skipped
+ */
+ @BeforeClass
+ public static void selectSuitableInterface() throws Exception {
+ Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
+ while(interfaces.hasMoreElements()) {
+ NetworkInterface intf = interfaces.nextElement();
+
+ System.out.println("Evaluating " + intf.getName());
+
+ if (intf.isLoopback()) {
+ suitableInterface = intf;
+
+ boolean hasIPv4 = false;
+ boolean hasIPv6 = false;
+ Enumeration<InetAddress> addresses = suitableInterface.getInetAddresses();
+ while (addresses.hasMoreElements()) {
- if (addresses.nextElement().getClass() == Inet6Address.class)
++ if (addresses.nextElement() instanceof Inet6Address)
+ hasIPv6 = true;
+ else
+ hasIPv4 = true;
+ }
+ hasIPv4andIPv6 = hasIPv4 && hasIPv6;
+ return;
+ }
+ }
+ }
+
+ @Test
+ public void testRpcInterface() throws Exception
+ {
+ Config testConfig = DatabaseDescriptor.loadConfig();
+ testConfig.rpc_interface = suitableInterface.getName();
+ testConfig.rpc_address = null;
+ DatabaseDescriptor.applyAddressConfig(testConfig);
+
+ /*
+ * Confirm ability to select between IPv4 and IPv6
+ */
+ if (hasIPv4andIPv6)
+ {
+ testConfig = DatabaseDescriptor.loadConfig();
+ testConfig.rpc_interface = suitableInterface.getName();
+ testConfig.rpc_address = null;
+ testConfig.rpc_interface_prefer_ipv6 = true;
+ DatabaseDescriptor.applyAddressConfig(testConfig);
+
+ assertEquals(DatabaseDescriptor.getRpcAddress().getClass(), Inet6Address.class);
+
+ testConfig = DatabaseDescriptor.loadConfig();
+ testConfig.rpc_interface = suitableInterface.getName();
+ testConfig.rpc_address = null;
+ testConfig.rpc_interface_prefer_ipv6 = false;
+ DatabaseDescriptor.applyAddressConfig(testConfig);
+
+ assertEquals(DatabaseDescriptor.getRpcAddress().getClass(), Inet4Address.class);
+ }
+ else
+ {
+ /*
+ * Confirm first address of interface is selected
+ */
+ assertEquals(DatabaseDescriptor.getRpcAddress(), suitableInterface.getInetAddresses().nextElement());
+ }
+ }
+
+ @Test
+ public void testListenInterface() throws Exception
+ {
+ Config testConfig = DatabaseDescriptor.loadConfig();
+ testConfig.listen_interface = suitableInterface.getName();
+ testConfig.listen_address = null;
+ DatabaseDescriptor.applyAddressConfig(testConfig);
+
+ /*
+ * Confirm ability to select between IPv4 and IPv6
+ */
+ if (hasIPv4andIPv6)
+ {
+ testConfig = DatabaseDescriptor.loadConfig();
+ testConfig.listen_interface = suitableInterface.getName();
+ testConfig.listen_address = null;
+ testConfig.listen_interface_prefer_ipv6 = true;
+ DatabaseDescriptor.applyAddressConfig(testConfig);
+
+ assertEquals(DatabaseDescriptor.getListenAddress().getClass(), Inet6Address.class);
+
+ testConfig = DatabaseDescriptor.loadConfig();
+ testConfig.listen_interface = suitableInterface.getName();
+ testConfig.listen_address = null;
+ testConfig.listen_interface_prefer_ipv6 = false;
+ DatabaseDescriptor.applyAddressConfig(testConfig);
+
+ assertEquals(DatabaseDescriptor.getListenAddress().getClass(), Inet4Address.class);
+ }
+ else
+ {
+ /*
+ * Confirm first address of interface is selected
+ */
+ assertEquals(DatabaseDescriptor.getRpcAddress(), suitableInterface.getInetAddresses().nextElement());
+ }
+ }
+
+ @Test
+ public void testListenAddress() throws Exception
+ {
+ Config testConfig = DatabaseDescriptor.loadConfig();
+ testConfig.listen_address = suitableInterface.getInterfaceAddresses().get(0).getAddress().getHostAddress();
+ testConfig.listen_interface = null;
+ DatabaseDescriptor.applyAddressConfig(testConfig);
+ }
+
+ @Test
+ public void testRpcAddress() throws Exception
+ {
+ Config testConfig = DatabaseDescriptor.loadConfig();
+ testConfig.rpc_address = suitableInterface.getInterfaceAddresses().get(0).getAddress().getHostAddress();
+ testConfig.rpc_interface = null;
+ DatabaseDescriptor.applyAddressConfig(testConfig);
+
+ }
}