mirror of https://github.com/apache/cassandra
Auto reload GossipingPropertyFileSnitch config
Patch by Danield Shelepov, reviewed by Tyler Hobbs for CASSANDRA-5897
This commit is contained in:
parent
728f677b0f
commit
f67b7a477a
|
|
@ -1,4 +1,5 @@
|
|||
2.1.0-beta2
|
||||
* Auto reload GossipingPropertyFileSnitch config (CASSANDRA-5897)
|
||||
* Fix overflow of memtable_total_space_in_mb (CASSANDRA-6573)
|
||||
* Fix ABTC NPE (CASSANDRA-6692)
|
||||
* Allow nodetool to use a file or prompt for password (CASSANDRA-6660)
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ public class Ec2Snitch extends AbstractNetworkTopologySnitch
|
|||
if (ec2region.endsWith("1"))
|
||||
ec2region = az.substring(0, az.length() - 3);
|
||||
|
||||
String datacenterSuffix = SnitchProperties.get("dc_suffix", "");
|
||||
String datacenterSuffix = (new SnitchProperties()).get("dc_suffix", "");
|
||||
ec2region = ec2region.concat(datacenterSuffix);
|
||||
logger.info("EC2Snitch using region: {}, zone: {}.", ec2region, ec2zone);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
package org.apache.cassandra.locator;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
|
|
@ -29,8 +30,10 @@ import org.apache.cassandra.exceptions.ConfigurationException;
|
|||
import org.apache.cassandra.gms.ApplicationState;
|
||||
import org.apache.cassandra.gms.EndpointState;
|
||||
import org.apache.cassandra.gms.Gossiper;
|
||||
import org.apache.cassandra.utils.FBUtilities;
|
||||
import org.apache.cassandra.service.StorageService;
|
||||
import org.apache.cassandra.utils.FBUtilities;
|
||||
import org.apache.cassandra.utils.ResourceWatcher;
|
||||
import org.apache.cassandra.utils.WrappedRunnable;
|
||||
|
||||
|
||||
public class GossipingPropertyFileSnitch extends AbstractNetworkTopologySnitch// implements IEndpointStateChangeSubscriber
|
||||
|
|
@ -38,23 +41,30 @@ public class GossipingPropertyFileSnitch extends AbstractNetworkTopologySnitch//
|
|||
private static final Logger logger = LoggerFactory.getLogger(GossipingPropertyFileSnitch.class);
|
||||
|
||||
private PropertyFileSnitch psnitch;
|
||||
private String myDC;
|
||||
private String myRack;
|
||||
private Map<InetAddress, Map<String, String>> savedEndpoints;
|
||||
private String DEFAULT_DC = "UNKNOWN_DC";
|
||||
private String DEFAULT_RACK = "UNKNOWN_RACK";
|
||||
private final boolean preferLocal;
|
||||
|
||||
private volatile String myDC;
|
||||
private volatile String myRack;
|
||||
private volatile boolean preferLocal;
|
||||
private AtomicReference<ReconnectableSnitchHelper> snitchHelperReference;
|
||||
private volatile boolean gossipStarted;
|
||||
|
||||
private Map<InetAddress, Map<String, String>> savedEndpoints;
|
||||
private static final String DEFAULT_DC = "UNKNOWN_DC";
|
||||
private static final String DEFAULT_RACK = "UNKNOWN_RACK";
|
||||
|
||||
private static final int DEFAULT_REFRESH_PERIOD_IN_SECONDS = 60;
|
||||
|
||||
public GossipingPropertyFileSnitch() throws ConfigurationException
|
||||
{
|
||||
myDC = SnitchProperties.get("dc", null);
|
||||
myRack = SnitchProperties.get("rack", null);
|
||||
if (myDC == null || myRack == null)
|
||||
throw new ConfigurationException("DC or rack not found in snitch properties, check your configuration in: " + SnitchProperties.RACKDC_PROPERTY_FILENAME);
|
||||
this(DEFAULT_REFRESH_PERIOD_IN_SECONDS);
|
||||
}
|
||||
|
||||
public GossipingPropertyFileSnitch(int refreshPeriodInSeconds) throws ConfigurationException
|
||||
{
|
||||
snitchHelperReference = new AtomicReference<ReconnectableSnitchHelper>();
|
||||
|
||||
reloadConfiguration();
|
||||
|
||||
myDC = myDC.trim();
|
||||
myRack = myRack.trim();
|
||||
preferLocal = Boolean.parseBoolean(SnitchProperties.get("prefer_local", "false"));
|
||||
try
|
||||
{
|
||||
psnitch = new PropertyFileSnitch();
|
||||
|
|
@ -64,6 +74,23 @@ public class GossipingPropertyFileSnitch extends AbstractNetworkTopologySnitch//
|
|||
{
|
||||
logger.info("Unable to load {}; compatibility mode disabled", PropertyFileSnitch.SNITCH_PROPERTIES_FILENAME);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
FBUtilities.resourceToFile(SnitchProperties.RACKDC_PROPERTY_FILENAME);
|
||||
Runnable runnable = new WrappedRunnable()
|
||||
{
|
||||
protected void runMayThrow() throws ConfigurationException
|
||||
{
|
||||
reloadConfiguration();
|
||||
}
|
||||
};
|
||||
ResourceWatcher.watch(SnitchProperties.RACKDC_PROPERTY_FILENAME, runnable, refreshPeriodInSeconds * 1000);
|
||||
}
|
||||
catch (ConfigurationException ex)
|
||||
{
|
||||
logger.error("{} found, but does not look like a plain file. Will not watch it for changes", SnitchProperties.RACKDC_PROPERTY_FILENAME);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -125,8 +152,55 @@ public class GossipingPropertyFileSnitch extends AbstractNetworkTopologySnitch//
|
|||
public void gossiperStarting()
|
||||
{
|
||||
super.gossiperStarting();
|
||||
|
||||
Gossiper.instance.addLocalApplicationState(ApplicationState.INTERNAL_IP,
|
||||
StorageService.instance.valueFactory.internalIP(FBUtilities.getLocalAddress().getHostAddress()));
|
||||
Gossiper.instance.register(new ReconnectableSnitchHelper(this, myDC, preferLocal));
|
||||
StorageService.instance.valueFactory.internalIP(FBUtilities.getLocalAddress().getHostAddress()));
|
||||
|
||||
reloadGossiperState();
|
||||
|
||||
gossipStarted = true;
|
||||
}
|
||||
|
||||
private void reloadConfiguration() throws ConfigurationException
|
||||
{
|
||||
final SnitchProperties properties = new SnitchProperties();
|
||||
|
||||
String newDc = properties.get("dc", null);
|
||||
String newRack = properties.get("rack", null);
|
||||
if (newDc == null || newRack == null)
|
||||
throw new ConfigurationException("DC or rack not found in snitch properties, check your configuration in: " + SnitchProperties.RACKDC_PROPERTY_FILENAME);
|
||||
|
||||
newDc = newDc.trim();
|
||||
newRack = newRack.trim();
|
||||
final boolean newPreferLocal = Boolean.parseBoolean(properties.get("prefer_local", "false"));
|
||||
|
||||
if (myDC != newDc || myRack != newRack || (preferLocal != newPreferLocal))
|
||||
{
|
||||
myDC = newDc;
|
||||
myRack = newRack;
|
||||
preferLocal = newPreferLocal;
|
||||
|
||||
reloadGossiperState();
|
||||
|
||||
if (StorageService.instance != null)
|
||||
StorageService.instance.getTokenMetadata().invalidateCachedRings();
|
||||
|
||||
if (gossipStarted)
|
||||
StorageService.instance.gossipSnitchInfo();
|
||||
}
|
||||
}
|
||||
|
||||
private void reloadGossiperState()
|
||||
{
|
||||
if (Gossiper.instance != null)
|
||||
{
|
||||
ReconnectableSnitchHelper pendingHelper = new ReconnectableSnitchHelper(this, myDC, preferLocal);
|
||||
Gossiper.instance.register(pendingHelper);
|
||||
|
||||
pendingHelper = snitchHelperReference.getAndSet(pendingHelper);
|
||||
if (pendingHelper != null)
|
||||
Gossiper.instance.unregister(pendingHelper);
|
||||
}
|
||||
// else this will eventually rerun at gossiperStarting()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ public class PropertyFileSnitch extends AbstractNetworkTopologySnitch
|
|||
}
|
||||
catch (ConfigurationException ex)
|
||||
{
|
||||
logger.debug("{} found, but does not look like a plain file. Will not watch it for changes", SNITCH_PROPERTIES_FILENAME);
|
||||
logger.error("{} found, but does not look like a plain file. Will not watch it for changes", SNITCH_PROPERTIES_FILENAME);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,10 +28,12 @@ public class SnitchProperties
|
|||
{
|
||||
private static final Logger logger = LoggerFactory.getLogger(SnitchProperties.class);
|
||||
public static final String RACKDC_PROPERTY_FILENAME = "cassandra-rackdc.properties";
|
||||
private static Properties properties = new Properties();
|
||||
|
||||
static
|
||||
private Properties properties;
|
||||
|
||||
public SnitchProperties()
|
||||
{
|
||||
properties = new Properties();
|
||||
InputStream stream = SnitchProperties.class.getClassLoader().getResourceAsStream(RACKDC_PROPERTY_FILENAME);
|
||||
try
|
||||
{
|
||||
|
|
@ -49,9 +51,9 @@ public class SnitchProperties
|
|||
}
|
||||
|
||||
/**
|
||||
* Get a snitch property value or return null if not defined.
|
||||
* Get a snitch property value or return defaultValue if not defined.
|
||||
*/
|
||||
public static String get(String propertyName, String defaultValue)
|
||||
public String get(String propertyName, String defaultValue)
|
||||
{
|
||||
return properties.getProperty(propertyName, defaultValue);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF 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.
|
||||
dc=DC2
|
||||
rack=RAC2
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF 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 org.apache.cassandra.locator;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import org.apache.cassandra.utils.FBUtilities;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link GossipingPropertyFileSnitch}.
|
||||
*/
|
||||
public class GossipingPropertyFileSnitchTest
|
||||
{
|
||||
@Test
|
||||
public void testAutoReloadConfig() throws Exception
|
||||
{
|
||||
String confFile = FBUtilities.resourceToFile(SnitchProperties.RACKDC_PROPERTY_FILENAME);
|
||||
|
||||
final GossipingPropertyFileSnitch snitch = new GossipingPropertyFileSnitch(/*refreshPeriodInSeconds*/1);
|
||||
YamlFileNetworkTopologySnitchTest.checkEndpoint(snitch, FBUtilities.getBroadcastAddress().getHostAddress(), "DC1", "RAC1");
|
||||
|
||||
final Path effectiveFile = Paths.get(confFile);
|
||||
final Path backupFile = Paths.get(confFile + ".bak");
|
||||
final Path modifiedFile = Paths.get(confFile + ".mod");
|
||||
|
||||
try
|
||||
{
|
||||
Files.copy(effectiveFile, backupFile);
|
||||
Files.copy(modifiedFile, effectiveFile, java.nio.file.StandardCopyOption.REPLACE_EXISTING);
|
||||
|
||||
Thread.sleep(1500);
|
||||
|
||||
YamlFileNetworkTopologySnitchTest.checkEndpoint(snitch, FBUtilities.getBroadcastAddress().getHostAddress(), "DC2", "RAC2");
|
||||
}
|
||||
finally
|
||||
{
|
||||
Files.copy(backupFile, effectiveFile, java.nio.file.StandardCopyOption.REPLACE_EXISTING);
|
||||
Files.delete(backupFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -88,7 +88,7 @@ public class YamlFileNetworkTopologySnitchTest
|
|||
* @param expectedRack
|
||||
* expected rack
|
||||
*/
|
||||
private void checkEndpoint(final AbstractNetworkTopologySnitch snitch,
|
||||
public static void checkEndpoint(final AbstractNetworkTopologySnitch snitch,
|
||||
final String endpointString, final String expectedDatacenter,
|
||||
final String expectedRack)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue