Author: jbellis
Date: Thu May 27 13:28:42 2010
New Revision: 948829
URL: http://svn.apache.org/viewvc?rev=948829&view=rev
Log:
Add ResourceWatcher to generalize reloading Strategy configurations. patch by
Jon Hermes and jbellis for CASSANDRA-1105
Added:
cassandra/trunk/src/java/org/apache/cassandra/utils/ResourceWatcher.java
Removed:
cassandra/trunk/src/java/org/apache/cassandra/locator/PropertyFileSnitchMBean.java
Modified:
cassandra/trunk/src/java/org/apache/cassandra/locator/DatacenterShardStrategy.java
cassandra/trunk/src/java/org/apache/cassandra/locator/PropertyFileSnitch.java
cassandra/trunk/src/java/org/apache/cassandra/utils/FBUtilities.java
Modified:
cassandra/trunk/src/java/org/apache/cassandra/locator/DatacenterShardStrategy.java
URL:
http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/locator/DatacenterShardStrategy.java?rev=948829&r1=948828&r2=948829&view=diff
==============================================================================
---
cassandra/trunk/src/java/org/apache/cassandra/locator/DatacenterShardStrategy.java
(original)
+++
cassandra/trunk/src/java/org/apache/cassandra/locator/DatacenterShardStrategy.java
Thu May 27 13:28:42 2010
@@ -1,4 +1,5 @@
package org.apache.cassandra.locator;
+
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -21,11 +22,7 @@ package org.apache.cassandra.locator;
*/
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.IOError;
import java.net.InetAddress;
-import java.net.URL;
import java.util.*;
import java.util.Map.Entry;
@@ -33,9 +30,11 @@ import com.google.common.collect.Multima
import org.apache.cassandra.config.ConfigurationException;
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.dht.Token;
+import org.apache.cassandra.utils.ResourceWatcher;
import org.apache.cassandra.service.*;
import org.apache.cassandra.thrift.ConsistencyLevel;
import org.apache.cassandra.utils.FBUtilities;
+import org.apache.cassandra.utils.WrappedRunnable;
/**
* This Replication Strategy takes a property file that gives the intended
@@ -63,38 +62,36 @@ public class DatacenterShardStrategy ext
if ((!(snitch instanceof AbstractRackAwareSnitch)))
throw new IllegalArgumentException("DatacenterShardStrategy
requires a rack-aware endpointsnitch");
this.snitch = (AbstractRackAwareSnitch)snitch;
-
- ClassLoader loader = PropertyFileSnitch.class.getClassLoader();
- URL scpurl = loader.getResource(DATACENTER_PROPERTY_FILENAME);
- if (scpurl == null)
- {
- throw new RuntimeException("unable to locate " +
DATACENTER_PROPERTY_FILENAME);
- }
- String dcPropertyFile = scpurl.getFile();
- try
- {
- Properties props = new Properties();
- props.load(new FileReader(dcPropertyFile));
- for (Object key : props.keySet())
+
+ reloadConfiguration();
+ Runnable runnable = new WrappedRunnable()
+ {
+ protected void runMayThrow() throws ConfigurationException
{
- String[] keys = ((String)key).split(":");
- Map<String, Integer> map = datacenters.get(keys[0]);
- if (null == map)
- {
- map = new HashMap<String, Integer>();
- }
- map.put(keys[1], Integer.parseInt((String)props.get(key)));
- datacenters.put(keys[0], map);
+ reloadConfiguration();
}
- }
- catch (IOException ioe)
- {
- throw new IOError(ioe);
- }
+ };
+ ResourceWatcher.watch(DATACENTER_PROPERTY_FILENAME, runnable, 60 *
1000);
loadEndpoints(tokenMetadata);
}
+ public void reloadConfiguration() throws ConfigurationException
+ {
+ Properties props =
PropertyFileSnitch.resourceToProperties(DATACENTER_PROPERTY_FILENAME);
+ for (Object key : props.keySet())
+ {
+ String[] keys = ((String)key).split(":");
+ Map<String, Integer> map = datacenters.get(keys[0]);
+ if (null == map)
+ {
+ map = new HashMap<String, Integer>();
+ }
+ map.put(keys[1], Integer.parseInt((String)props.get(key)));
+ datacenters.put(keys[0], map);
+ }
+ }
+
private synchronized void loadEndpoints(TokenMetadata metadata) throws
ConfigurationException
{
String localDC =
snitch.getDatacenter(DatabaseDescriptor.getListenAddress());
Modified:
cassandra/trunk/src/java/org/apache/cassandra/locator/PropertyFileSnitch.java
URL:
http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/locator/PropertyFileSnitch.java?rev=948829&r1=948828&r2=948829&view=diff
==============================================================================
---
cassandra/trunk/src/java/org/apache/cassandra/locator/PropertyFileSnitch.java
(original)
+++
cassandra/trunk/src/java/org/apache/cassandra/locator/PropertyFileSnitch.java
Thu May 27 13:28:42 2010
@@ -20,18 +20,14 @@ package org.apache.cassandra.locator;
import java.io.FileReader;
import java.io.IOException;
-import java.lang.management.ManagementFactory;
-import java.net.UnknownHostException;
-import java.net.URL;
+import java.net.InetAddress;
import java.util.Properties;
import java.util.StringTokenizer;
-import javax.management.MBeanServer;
-import javax.management.ObjectName;
-
-import java.net.InetAddress;
-
import org.apache.cassandra.config.ConfigurationException;
+import org.apache.cassandra.utils.FBUtilities;
+import org.apache.cassandra.utils.ResourceWatcher;
+import org.apache.cassandra.utils.WrappedRunnable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -40,11 +36,11 @@ import org.slf4j.LoggerFactory;
* <p/>
* Based on a properties file configuration.
*/
-public class PropertyFileSnitch extends AbstractRackAwareSnitch implements
PropertyFileSnitchMBean {
+public class PropertyFileSnitch extends AbstractRackAwareSnitch {
/**
* A list of properties with keys being host:port and values being
datacenter:rack
*/
- private Properties hostProperties = new Properties();
+ private volatile Properties hostProperties = new Properties();
/**
* The default rack property file to be read.
@@ -56,18 +52,16 @@ public class PropertyFileSnitch extends
*/
private static Logger logger_ =
LoggerFactory.getLogger(PropertyFileSnitch.class);
- public PropertyFileSnitch() throws ConfigurationException
- {
+ public PropertyFileSnitch() throws ConfigurationException {
reloadConfiguration();
- try
- {
- MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
- mbs.registerMBean(this, new ObjectName(MBEAN_OBJECT_NAME));
- }
- catch (Exception e)
+ Runnable runnable = new WrappedRunnable()
{
- throw new RuntimeException(e);
- }
+ protected void runMayThrow() throws ConfigurationException
+ {
+ reloadConfiguration();
+ }
+ };
+ ResourceWatcher.watch(RACK_PROPERTY_FILENAME, runnable, 60 * 1000);
}
/**
@@ -115,40 +109,25 @@ public class PropertyFileSnitch extends
return getEndpointInfo(endpoint)[1];
}
- /**
- * @return the <tt>String</tt> representation of the configuration
- */
- public String displayConfiguration() {
- StringBuffer configurationString = new StringBuffer("Current rack
configuration\n=================\n");
- for (Object key: hostProperties.keySet()) {
- String endpoint = (String) key;
- String value = hostProperties.getProperty(endpoint);
-
configurationString.append(endpoint).append("=").append(value).append("\n");
- }
- return configurationString.toString();
- }
-
- /**
- * Reloads the configuration from the file
- */
public void reloadConfiguration() throws ConfigurationException
{
- ClassLoader loader = PropertyFileSnitch.class.getClassLoader();
- URL scpurl = loader.getResource(RACK_PROPERTY_FILENAME);
- if (scpurl == null)
- throw new ConfigurationException("unable to locate " +
RACK_PROPERTY_FILENAME);
+ hostProperties = resourceToProperties(RACK_PROPERTY_FILENAME);
+ }
- String rackPropertyFilename = scpurl.getFile();
+ public static Properties resourceToProperties(String filename) throws
ConfigurationException
+ {
+ String rackPropertyFilename = FBUtilities.resourceToFile(filename);
+ Properties localHostProperties;
try
{
- Properties localHostProperties = new Properties();
+ localHostProperties = new Properties();
localHostProperties.load(new FileReader(rackPropertyFilename));
- hostProperties = localHostProperties;
}
- catch (IOException ioe)
+ catch (IOException e)
{
- throw new ConfigurationException("Could not process " +
rackPropertyFilename, ioe);
+ throw new ConfigurationException("Unable to load " +
rackPropertyFilename, e);
}
+ return localHostProperties;
}
}
Modified: cassandra/trunk/src/java/org/apache/cassandra/utils/FBUtilities.java
URL:
http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/utils/FBUtilities.java?rev=948829&r1=948828&r2=948829&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/utils/FBUtilities.java
(original)
+++ cassandra/trunk/src/java/org/apache/cassandra/utils/FBUtilities.java Thu
May 27 13:28:42 2010
@@ -21,6 +21,7 @@ package org.apache.cassandra.utils;
import java.io.*;
import java.math.BigInteger;
import java.net.InetAddress;
+import java.net.URL;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
@@ -33,6 +34,8 @@ import java.util.zip.DataFormatException
import java.util.zip.Deflater;
import java.util.zip.Inflater;
+import org.apache.cassandra.config.ConfigurationException;
+import org.apache.cassandra.locator.PropertyFileSnitch;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -548,4 +551,14 @@ public class FBUtilities
ByteBuffer.wrap(bytes).putLong(n);
return bytes;
}
+
+ public static String resourceToFile(String filename) throws
ConfigurationException
+ {
+ ClassLoader loader = PropertyFileSnitch.class.getClassLoader();
+ URL scpurl = loader.getResource(filename);
+ if (scpurl == null)
+ throw new ConfigurationException("unable to locate " + filename);
+
+ return scpurl.getFile();
+ }
}
Added: cassandra/trunk/src/java/org/apache/cassandra/utils/ResourceWatcher.java
URL:
http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/utils/ResourceWatcher.java?rev=948829&view=auto
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/utils/ResourceWatcher.java
(added)
+++ cassandra/trunk/src/java/org/apache/cassandra/utils/ResourceWatcher.java
Thu May 27 13:28:42 2010
@@ -0,0 +1,51 @@
+package org.apache.cassandra.utils;
+
+import java.io.File;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ResourceWatcher
+{
+ private static Timer timer = new Timer("RESOURCE-WATCHER");
+
+ public static void watch(String resource, Runnable callback, int period)
+ {
+ timer.schedule(new WatchedResource(resource, callback), period,
period);
+ }
+
+ public static class WatchedResource extends TimerTask
+ {
+ private static Logger logger =
LoggerFactory.getLogger(WatchedResource.class);
+ private String resource;
+ private Runnable callback;
+ private long lastLoaded;
+
+ public WatchedResource(String resource, Runnable callback)
+ {
+ this.resource = resource;
+ this.callback = callback;
+ lastLoaded = 0;
+ }
+
+ public void run()
+ {
+ try
+ {
+ String filename = FBUtilities.resourceToFile(resource);
+ long lastModified = new File(filename).lastModified();
+ if (lastModified > lastLoaded)
+ {
+ callback.run();
+ lastLoaded = lastModified;
+ }
+ }
+ catch (Throwable t)
+ {
+ logger.error(String.format("Timed run of %s failed.",
callback.getClass()), t);
+ }
+ }
+ }
+}