Skip to content

Commit

Permalink
forward-port CASSANDRA-1481. originally thought it was a non-issue in…
Browse files Browse the repository at this point in the history
… 0.7 because of endpoint caching in Strategy, but getRack/getDatacenter are still called by sortByProximity in StorageProxy. patch by jbellis

git-svn-id: https://svn.apache.org/repos/asf/cassandra/trunk@1022690 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
jbellis committed Oct 14, 2010
1 parent 1e233d7 commit 0f89876
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 40 deletions.
4 changes: 4 additions & 0 deletions CHANGES.txt
Expand Up @@ -34,6 +34,10 @@ dev
* fix removing tokens from SystemTable on decommission and removetoken
(CASSANDRA-1609)
* include CF metadata in cli 'show keyspaces' (CASSANDRA-1613)
* switch from Properties to HashMap in PropertyFileSnitch to
avoid synchronization bottleneck (CASSANDRA-1481)
* PropertyFileSnitch configuration file renamed to
cassandra-topology.properties


0.7-beta2
Expand Down
2 changes: 2 additions & 0 deletions NEWS.txt
Expand Up @@ -76,6 +76,8 @@ Configuraton
------------
- Configuration file renamed to cassandra.yaml and log4j.properties to
log4j-server.properties
- PropertyFileSnitch configuration file renamed to
cassandra-topology.properties
- The ThriftAddress and ThriftPort directives have been renamed to
RPCAddress and RPCPort respectively.
- EndPointSnitch was renamed to RackInferringSnitch. A new SimpleSnitch
Expand Down
Expand Up @@ -15,8 +15,8 @@
# limitations under the License.

# Cassandra Node IP=Data Center:Rack
192.168.1.200=DC1:RAC1
192.168.2.300=DC2:RAC2
192.168.1.100=DC1:RAC1
192.168.2.200=DC2:RAC2

10.0.0.10=DC1:RAC1
10.0.0.11=DC1:RAC1
Expand Down
93 changes: 56 additions & 37 deletions src/java/org/apache/cassandra/locator/PropertyFileSnitch.java
Expand Up @@ -21,8 +21,10 @@
import java.io.FileReader;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.StringTokenizer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -35,24 +37,21 @@
/**
* Used to determine if two IP's are in the same datacenter or on the same rack.
* <p/>
* Based on a properties file configuration.
* Based on a properties file in the following format:
*
* 10.0.0.13=DC1:RAC2
* 10.21.119.14=DC3:RAC2
* 10.20.114.15=DC2:RAC2
* default=DC1:r1
*/
public class PropertyFileSnitch extends AbstractNetworkTopologySnitch
{
/**
* A list of properties with keys being host:port and values being datacenter:rack
*/
private volatile Properties hostProperties;
private static final Logger logger = LoggerFactory.getLogger(PropertyFileSnitch.class);

/**
* The default rack property file to be read.
*/
private static String RACK_PROPERTY_FILENAME = "cassandra-rack.properties";
private static final String RACK_PROPERTY_FILENAME = "cassandra-topology.properties";

/**
* Reference to the logger.
*/
private static Logger logger_ = LoggerFactory.getLogger(PropertyFileSnitch.class);
private static volatile Map<InetAddress, String[]> endpointMap;
private static volatile String[] defaultDCRack;

public PropertyFileSnitch() throws ConfigurationException
{
Expand All @@ -75,20 +74,13 @@ protected void runMayThrow() throws ConfigurationException
*/
public String[] getEndpointInfo(InetAddress endpoint)
{
String key = endpoint.getHostAddress();
String value = hostProperties.getProperty(key);
String[] value = endpointMap.get(endpoint);
if (value == null)
{
logger_.error("Could not find end point information for {}, will use default.", key);
value = hostProperties.getProperty("default");
}
StringTokenizer st = new StringTokenizer(value, ":");
if (st.countTokens() < 2)
{
logger_.error("Value for " + key + " is invalid: " + value);
return new String[] { "default", "default" };
logger.debug("Could not find end point information for {}, will use default", endpoint);
return defaultDCRack;
}
return new String[] { st.nextToken(), st.nextToken() };
return value;
}

/**
Expand All @@ -115,24 +107,51 @@ public String getRack(InetAddress endpoint)

public void reloadConfiguration() throws ConfigurationException
{
hostProperties = resourceToProperties(RACK_PROPERTY_FILENAME);
clearEndpointCache();
}
HashMap<InetAddress, String[]> reloadedMap = new HashMap<InetAddress, String[]>();

public static Properties resourceToProperties(String filename) throws ConfigurationException
{
String rackPropertyFilename = FBUtilities.resourceToFile(filename);

Properties localHostProperties;
String rackPropertyFilename = FBUtilities.resourceToFile(RACK_PROPERTY_FILENAME);
Properties properties = new Properties();
try
{
localHostProperties = new Properties();
localHostProperties.load(new FileReader(rackPropertyFilename));
properties.load(new FileReader(rackPropertyFilename));
}
catch (IOException e)
{
throw new ConfigurationException("Unable to load " + rackPropertyFilename, e);
throw new ConfigurationException("Unable to read " + RACK_PROPERTY_FILENAME, e);
}
return localHostProperties;

for (Map.Entry<Object, Object> entry : properties.entrySet())
{
String key = (String) entry.getKey();
String value = (String) entry.getValue();

if (key.equals("default"))
{
defaultDCRack = value.split(":");
if (defaultDCRack.length < 2)
defaultDCRack = new String[] { "default", "default" };
}
else
{
InetAddress host;
String hostString = key.replace("/", "");
try
{
host = InetAddress.getByName(hostString);
}
catch (UnknownHostException e)
{
throw new ConfigurationException("Unknown host " + hostString, e);
}
String[] token = value.split(":");
if (token.length < 2)
token = new String[] { "default", "default" };
reloadedMap.put(host, token);
}
}

logger.debug("loaded network topology {}", FBUtilities.toString(reloadedMap));
endpointMap = reloadedMap;
clearEndpointCache();
}
}
8 changes: 7 additions & 1 deletion src/java/org/apache/cassandra/utils/FBUtilities.java
Expand Up @@ -676,9 +676,15 @@ public static String toString(Map<?,?> map)
StringBuilder sb = new StringBuilder("{");
for (Map.Entry<?,?> entry : map.entrySet())
{
sb.append(entry.getKey()).append(": ").append(entry.getValue()).append(", ");
sb.append(toString(entry.getKey())).append(": ").append(toString(entry.getValue())).append(", ");
}
sb.append("}");
return sb.toString();
}

/** slow! */
private static Object toString(Object o)
{
return o.getClass().isArray() ? Arrays.toString((Object[]) o) : o.toString();
}
}

0 comments on commit 0f89876

Please sign in to comment.