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/tagging-services-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/patch/*-context.xml" />
</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 -->
<bean id="fileSystemClusterConfig" class="org.alfresco.filesys.config.ClusterConfigBean">
<property name="clusterEnabled">
<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="hazelcastInstanceFactory" ref="hazelcastInstanceFactory"/>
<property name="debugFlags">
<value>${filesystem.cluster.debugFlags}</value>
</property>

View File

@@ -26,22 +26,6 @@
</bean>
<bean id="webdavLockStoreFactory" class="org.alfresco.repo.webdav.LockStoreFactoryImpl">
<property name="clusterName" value="${alfresco.cluster.name}"/>
<property name="hazelcastInstanceFactory" ref="hazelcastInstanceFactory"/>
</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>

View File

@@ -18,6 +18,8 @@
*/
package org.alfresco.filesys.config;
import org.alfresco.repo.cluster.HazelcastInstanceFactory;
/**
* The Class ClusterConfigBean.
*
@@ -26,40 +28,29 @@ package org.alfresco.filesys.config;
*/
public class ClusterConfigBean
{
private boolean isClusterEnabled = false;
private String configFile;
private String clusterName;
private HazelcastInstanceFactory hazelcastInstanceFactory;
private String debugFlags;
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()
{
return isClusterEnabled;
return hazelcastInstanceFactory.isClusteringEnabled();
}
public void setClusterName(String clusterName)
{
this.clusterName = clusterName;
}
public String getClusterName()
{
return clusterName;
}
public void setConfigFile(String configFile)
{
this.configFile = configFile;
}
public String getConfigFile()
{
return configFile;
return hazelcastInstanceFactory.getClusterName();
}
public void setDebugFlags(String debugFlags)

View File

@@ -19,7 +19,6 @@
package org.alfresco.filesys.config;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.InetAddress;
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.StringList;
import org.alfresco.jlan.util.X64;
import org.alfresco.repo.cluster.HazelcastInstanceFactory;
import org.alfresco.repo.management.subsystems.ActivateableBean;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.extensions.config.element.GenericConfigElement;
@@ -2323,32 +2323,13 @@ public class ServerConfigurationBean extends AbstractServerConfigurationBean imp
logger.info("Filesystem cluster cache not enabled");
return;
}
String clusterName = clusterConfigBean.getClusterName();
if (clusterName == null || clusterName.length() == 0)
{
throw new InvalidConfigurationException("Cluster name not specified or invalid");
}
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);
}
// Create a ClusterConfigSection and attach it to 'this'.
ClusterConfigSection clusterConf = new ClusterConfigSection(this);
HazelcastInstanceFactory hazelcastInstanceFactory = clusterConfigBean.getHazelcastInstanceFactory();
// Clustering is enabled, so we can safely request the hazelcast instance.
HazelcastInstance hazelcast = hazelcastInstanceFactory.getInstance();
clusterConf.setHazelcastInstance(hazelcast);
}

View File

@@ -18,34 +18,122 @@
*/
package org.alfresco.repo.cluster;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.alfresco.util.PropertyCheck;
import com.hazelcast.config.Config;
import com.hazelcast.core.Hazelcast;
import com.hazelcast.core.HazelcastInstance;
/**
* 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>
* An intermediary class such as this is required in order to avoid starting
* Hazelcast instances when clustering is not configured/required. Otherwise
* 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
*/
public class HazelcastInstanceFactory
{
public Config config;
public HazelcastInstance newInstance()
private Config config;
private HazelcastInstance hazelcastInstance;
/** Guards {@link #config} and {@link #hazelcastInstance} */
private ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
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)
{
this.config = config;
rwLock.writeLock().lock();
try
{
this.config = config;
}
finally
{
rwLock.writeLock().unlock();
}
}
}

View File

@@ -26,5 +26,5 @@ package org.alfresco.repo.webdav;
*/
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.service.cmr.repository.NodeRef;
import org.alfresco.util.PropertyCheck;
import com.hazelcast.core.HazelcastInstance;
/**
* 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}.
*
* @see LockStoreFactory
@@ -40,22 +39,21 @@ public class LockStoreFactoryImpl implements LockStoreFactory
{
private static final String HAZELCAST_MAP_NAME = "webdav-locks";
private HazelcastInstanceFactory hazelcastInstanceFactory;
private String clusterName;
/**
* This method should be used sparingly and the created {@link LockStore}s should be
* retained (this factory does not cache instances of them).
*/
@Override
public synchronized LockStore getLockStore()
public synchronized LockStore createLockStore()
{
if (!PropertyCheck.isValidPropertyString(clusterName))
if (!hazelcastInstanceFactory.isClusteringEnabled())
{
return new SimpleLockStore();
}
else
{
HazelcastInstance instance = hazelcastInstanceFactory.newInstance();
HazelcastInstance instance = hazelcastInstanceFactory.getInstance();
ConcurrentMap<NodeRef, LockInfo> map = instance.getMap(HAZELCAST_MAP_NAME);
return new LockStoreImpl(map);
}
@@ -68,12 +66,4 @@ public class LockStoreFactoryImpl implements LockStoreFactory
{
this.hazelcastInstanceFactory = hazelcastInstanceFactory;
}
/**
* @param clusterName the clusterName to set
*/
public synchronized void setClusterName(String clusterName)
{
this.clusterName = clusterName;
}
}