Merged BRANCHES/DEV/mward/cifs_hazelcast_conf to HEAD:

36500: ALF-13821: CIFS and WebDAV should use same Hazelcast configuration mechanism
   36507: ALF-13821: CIFS and WebDAV should use same Hazelcast configuration mechanism
   36511: ALF-13821: CIFS and WebDAV should use same Hazelcast configuration mechanism
   36519: ALF-13821: Extract hazelcastConfig, hazelcastInstanceFactory bean definitions from webdav-context.xml to cluster-context.xml
   36553: ALF-13821: CIFS and WebDAV should use same Hazelcast configuration mechanism

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@36581 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Matt Ward
2012-05-18 18:10:02 +00:00
parent d437d5105d
commit bc532d64b8
9 changed files with 142 additions and 97 deletions

View File

@@ -43,6 +43,7 @@
<import resource="classpath:alfresco/activities/activities-feed-context.xml" /> <import resource="classpath:alfresco/activities/activities-feed-context.xml" />
<import resource="classpath:alfresco/tagging-services-context.xml"/> <import resource="classpath:alfresco/tagging-services-context.xml"/>
<import resource="classpath:alfresco/invitation-service-context.xml"/> <import resource="classpath:alfresco/invitation-service-context.xml"/>
<import resource="classpath:alfresco/cluster-context.xml"/>
<import resource="classpath:alfresco/webdav-context.xml"/> <import resource="classpath:alfresco/webdav-context.xml"/>
<import resource="classpath*:alfresco/patch/*-context.xml" /> <import resource="classpath*:alfresco/patch/*-context.xml" />
</beans> </beans>

View File

@@ -0,0 +1,18 @@
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
<beans>
<bean id="hazelcastConfig" class="org.alfresco.repo.cluster.HazelcastConfigFactoryBean">
<property name="configFile" value="${alfresco.hazelcast.configLocation}"/>
<property name="properties">
<props>
<prop key="alfresco.cluster.name">${alfresco.cluster.name}</prop>
<prop key="alfresco.hazelcast.password">${alfresco.hazelcast.password}</prop>
</props>
</property>
</bean>
<bean id="hazelcastInstanceFactory" class="org.alfresco.repo.cluster.HazelcastInstanceFactory">
<property name="config" ref="hazelcastConfig"/>
</bean>
</beans>

View File

@@ -288,15 +288,7 @@
<!-- Cluster Configuration --> <!-- Cluster Configuration -->
<bean id="fileSystemClusterConfig" class="org.alfresco.filesys.config.ClusterConfigBean"> <bean id="fileSystemClusterConfig" class="org.alfresco.filesys.config.ClusterConfigBean">
<property name="clusterEnabled"> <property name="hazelcastInstanceFactory" ref="hazelcastInstanceFactory"/>
<value>${filesystem.cluster.enabled}</value>
</property>
<property name="clusterName">
<value>${filesystem.cluster.name}</value>
</property>
<property name="configFile">
<value>${filesystem.cluster.configFile}</value>
</property>
<property name="debugFlags"> <property name="debugFlags">
<value>${filesystem.cluster.debugFlags}</value> <value>${filesystem.cluster.debugFlags}</value>
</property> </property>

View File

@@ -26,22 +26,6 @@
</bean> </bean>
<bean id="webdavLockStoreFactory" class="org.alfresco.repo.webdav.LockStoreFactoryImpl"> <bean id="webdavLockStoreFactory" class="org.alfresco.repo.webdav.LockStoreFactoryImpl">
<property name="clusterName" value="${alfresco.cluster.name}"/>
<property name="hazelcastInstanceFactory" ref="hazelcastInstanceFactory"/> <property name="hazelcastInstanceFactory" ref="hazelcastInstanceFactory"/>
</bean> </bean>
<bean id="hazelcastConfig" class="org.alfresco.repo.cluster.HazelcastConfigFactoryBean">
<property name="configFile" value="${alfresco.hazelcast.configLocation}"/>
<property name="properties">
<props>
<prop key="alfresco.cluster.name">${alfresco.cluster.name}</prop>
<prop key="alfresco.hazelcast.password">${alfresco.hazelcast.password}</prop>
</props>
</property>
</bean>
<bean id="hazelcastInstanceFactory" class="org.alfresco.repo.cluster.HazelcastInstanceFactory">
<property name="config" ref="hazelcastConfig"/>
</bean>
</beans> </beans>

View File

@@ -18,6 +18,8 @@
*/ */
package org.alfresco.filesys.config; package org.alfresco.filesys.config;
import org.alfresco.repo.cluster.HazelcastInstanceFactory;
/** /**
* The Class ClusterConfigBean. * The Class ClusterConfigBean.
* *
@@ -26,40 +28,29 @@ package org.alfresco.filesys.config;
*/ */
public class ClusterConfigBean public class ClusterConfigBean
{ {
private boolean isClusterEnabled = false; private HazelcastInstanceFactory hazelcastInstanceFactory;
private String configFile;
private String clusterName;
private String debugFlags; private String debugFlags;
private int nearCacheTimeout; private int nearCacheTimeout;
public void setClusterEnabled(boolean clusterEnabled)
public void setHazelcastInstanceFactory(HazelcastInstanceFactory hazelcastInstanceFactory)
{ {
this.isClusterEnabled = clusterEnabled; this.hazelcastInstanceFactory = hazelcastInstanceFactory;
}
public HazelcastInstanceFactory getHazelcastInstanceFactory()
{
return this.hazelcastInstanceFactory;
} }
public boolean getClusterEnabled() public boolean getClusterEnabled()
{ {
return isClusterEnabled; return hazelcastInstanceFactory.isClusteringEnabled();
}
public void setClusterName(String clusterName)
{
this.clusterName = clusterName;
} }
public String getClusterName() public String getClusterName()
{ {
return clusterName; return hazelcastInstanceFactory.getClusterName();
}
public void setConfigFile(String configFile)
{
this.configFile = configFile;
}
public String getConfigFile()
{
return configFile;
} }
public void setDebugFlags(String debugFlags) public void setDebugFlags(String debugFlags)

View File

@@ -19,7 +19,6 @@
package org.alfresco.filesys.config; package org.alfresco.filesys.config;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
@@ -83,6 +82,7 @@ import org.alfresco.jlan.util.MemorySize;
import org.alfresco.jlan.util.Platform; import org.alfresco.jlan.util.Platform;
import org.alfresco.jlan.util.StringList; import org.alfresco.jlan.util.StringList;
import org.alfresco.jlan.util.X64; import org.alfresco.jlan.util.X64;
import org.alfresco.repo.cluster.HazelcastInstanceFactory;
import org.alfresco.repo.management.subsystems.ActivateableBean; import org.alfresco.repo.management.subsystems.ActivateableBean;
import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.DisposableBean;
import org.springframework.extensions.config.element.GenericConfigElement; import org.springframework.extensions.config.element.GenericConfigElement;
@@ -2324,31 +2324,12 @@ public class ServerConfigurationBean extends AbstractServerConfigurationBean imp
return; return;
} }
String clusterName = clusterConfigBean.getClusterName(); // Create a ClusterConfigSection and attach it to 'this'.
if (clusterName == null || clusterName.length() == 0) ClusterConfigSection clusterConf = new ClusterConfigSection(this);
{ HazelcastInstanceFactory hazelcastInstanceFactory = clusterConfigBean.getHazelcastInstanceFactory();
throw new InvalidConfigurationException("Cluster name not specified or invalid"); // Clustering is enabled, so we can safely request the hazelcast instance.
} HazelcastInstance hazelcast = hazelcastInstanceFactory.getInstance();
clusterConf.setHazelcastInstance(hazelcast);
String clusterFile = clusterConfigBean.getConfigFile();
if (clusterFile == null || clusterFile.length() == 0)
{
throw new InvalidConfigurationException("Cluster config file not specified or invalid");
}
// New Hazelcast instance created here within the ClusterConfigSection
ClusterConfigSection jlanClusterConfig = new ClusterConfigSection(this);
try
{
//TODO replace config XML file with Hazelcast config bean backed by spring.
jlanClusterConfig.setConfigFile(clusterFile);
HazelcastInstance hazelcastInstance = jlanClusterConfig.getHazelcastInstance();
}
catch (FileNotFoundException e)
{
throw new InvalidConfigurationException("Unable to start filsystem cluster", e);
}
} }

View File

@@ -18,34 +18,122 @@
*/ */
package org.alfresco.repo.cluster; package org.alfresco.repo.cluster;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.alfresco.util.PropertyCheck;
import com.hazelcast.config.Config; import com.hazelcast.config.Config;
import com.hazelcast.core.Hazelcast; import com.hazelcast.core.Hazelcast;
import com.hazelcast.core.HazelcastInstance; import com.hazelcast.core.HazelcastInstance;
/** /**
* Provides a way of lazily creating HazelcastInstances for a given configuration. * Provides a way of lazily creating HazelcastInstances for a given configuration.
* The HazelcastInstance will not be created until {@link #newInstance()} is called. * The HazelcastInstance will not be created until {@link #getInstance()} is called.
* <p> * <p>
* An intermediary class such as this is required in order to avoid starting * An intermediary class such as this is required in order to avoid starting
* Hazelcast instances when clustering is not configured/required. Otherwise * Hazelcast instances when clustering is not configured/required. Otherwise
* simply by defining a HazelcastInstance bean clustering would spring into life. * simply by defining a HazelcastInstance bean clustering would spring into life.
* <p>
* Please note this class provides non-static access deliberately, and should be
* injected into any clients that require its services.
* *
* @author Matt Ward * @author Matt Ward
*/ */
public class HazelcastInstanceFactory public class HazelcastInstanceFactory
{ {
public Config config; private Config config;
private HazelcastInstance hazelcastInstance;
/** Guards {@link #config} and {@link #hazelcastInstance} */
private ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
public HazelcastInstance newInstance() public HazelcastInstance getInstance()
{ {
return Hazelcast.newHazelcastInstance(config); rwLock.readLock().lock();
try
{
if (hazelcastInstance != null)
{
return hazelcastInstance;
}
}
finally
{
rwLock.readLock().unlock();
}
// hazelcastInstance is null, so create it.
rwLock.writeLock().lock();
try
{
// Double check condition hasn't changed in between locks.
if (hazelcastInstance == null)
{
hazelcastInstance = Hazelcast.newHazelcastInstance(config);
}
return hazelcastInstance;
}
finally
{
rwLock.writeLock().unlock();
}
} }
/** /**
* @param config the config to set * Checks whether hazelcast has been given a valid cluster name. If so,
* then clustering is considered enabled. This condition should be checked
* before calling {@link #getInstance()}.
*
* @return true if clustering is enabled, false otherwise.
*/
public boolean isClusteringEnabled()
{
rwLock.readLock().lock();
try
{
String clusterName = config.getGroupConfig().getName();
return (PropertyCheck.isValidPropertyString(clusterName));
}
finally
{
rwLock.readLock().unlock();
}
}
/**
* Retrieve the name of the cluster for the configuration used by this factory.
*
* @return String - the cluster name.
*/
public String getClusterName()
{
rwLock.readLock().lock();
try
{
String clusterName = config.getGroupConfig().getName();
return clusterName;
}
finally
{
rwLock.readLock().unlock();
}
}
/**
* Sets the Hazelcast configuration that will be used by this factory when
* creating the HazelcastInstance.
*
* @param config Hazelcast configuration
*/ */
public void setConfig(Config config) public void setConfig(Config config)
{
rwLock.writeLock().lock();
try
{ {
this.config = config; this.config = config;
} }
finally
{
rwLock.writeLock().unlock();
}
}
} }

View File

@@ -26,5 +26,5 @@ package org.alfresco.repo.webdav;
*/ */
public interface LockStoreFactory public interface LockStoreFactory
{ {
LockStore getLockStore(); LockStore createLockStore();
} }

View File

@@ -22,14 +22,13 @@ import java.util.concurrent.ConcurrentMap;
import org.alfresco.repo.cluster.HazelcastInstanceFactory; import org.alfresco.repo.cluster.HazelcastInstanceFactory;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.util.PropertyCheck;
import com.hazelcast.core.HazelcastInstance; import com.hazelcast.core.HazelcastInstance;
/** /**
* Default implementation of the {@link LockStoreFactory} interface. Creates {@link LockStore}s * Default implementation of the {@link LockStoreFactory} interface. Creates {@link LockStore}s
* backed by a Hazelcast distributed Map if the clusterName property is set, * backed by a Hazelcast distributed Map if clustering is enabled,
* otherwise it creates a non-clustered {@link SimpleLockStore}. * otherwise it creates a non-clustered {@link SimpleLockStore}.
* *
* @see LockStoreFactory * @see LockStoreFactory
@@ -40,22 +39,21 @@ public class LockStoreFactoryImpl implements LockStoreFactory
{ {
private static final String HAZELCAST_MAP_NAME = "webdav-locks"; private static final String HAZELCAST_MAP_NAME = "webdav-locks";
private HazelcastInstanceFactory hazelcastInstanceFactory; private HazelcastInstanceFactory hazelcastInstanceFactory;
private String clusterName;
/** /**
* This method should be used sparingly and the created {@link LockStore}s should be * This method should be used sparingly and the created {@link LockStore}s should be
* retained (this factory does not cache instances of them). * retained (this factory does not cache instances of them).
*/ */
@Override @Override
public synchronized LockStore getLockStore() public synchronized LockStore createLockStore()
{ {
if (!PropertyCheck.isValidPropertyString(clusterName)) if (!hazelcastInstanceFactory.isClusteringEnabled())
{ {
return new SimpleLockStore(); return new SimpleLockStore();
} }
else else
{ {
HazelcastInstance instance = hazelcastInstanceFactory.newInstance(); HazelcastInstance instance = hazelcastInstanceFactory.getInstance();
ConcurrentMap<NodeRef, LockInfo> map = instance.getMap(HAZELCAST_MAP_NAME); ConcurrentMap<NodeRef, LockInfo> map = instance.getMap(HAZELCAST_MAP_NAME);
return new LockStoreImpl(map); return new LockStoreImpl(map);
} }
@@ -68,12 +66,4 @@ public class LockStoreFactoryImpl implements LockStoreFactory
{ {
this.hazelcastInstanceFactory = hazelcastInstanceFactory; this.hazelcastInstanceFactory = hazelcastInstanceFactory;
} }
/**
* @param clusterName the clusterName to set
*/
public synchronized void setClusterName(String clusterName)
{
this.clusterName = clusterName;
}
} }