From bc532d64b8517fd31d343c6d75a794fcc43d74fb Mon Sep 17 00:00:00 2001 From: Matt Ward Date: Fri, 18 May 2012 18:10:02 +0000 Subject: [PATCH] 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 --- config/alfresco/application-context-core.xml | 1 + config/alfresco/cluster-context.xml | 18 ++++ .../default/file-servers-context.xml | 10 +- config/alfresco/webdav-context.xml | 16 --- .../filesys/config/ClusterConfigBean.java | 37 +++---- .../config/ServerConfigurationBean.java | 35 ++---- .../cluster/HazelcastInstanceFactory.java | 102 ++++++++++++++++-- .../repo/webdav/LockStoreFactory.java | 2 +- .../repo/webdav/LockStoreFactoryImpl.java | 18 +--- 9 files changed, 142 insertions(+), 97 deletions(-) create mode 100644 config/alfresco/cluster-context.xml diff --git a/config/alfresco/application-context-core.xml b/config/alfresco/application-context-core.xml index 5e9b9851a9..32fc63545e 100644 --- a/config/alfresco/application-context-core.xml +++ b/config/alfresco/application-context-core.xml @@ -43,6 +43,7 @@ + diff --git a/config/alfresco/cluster-context.xml b/config/alfresco/cluster-context.xml new file mode 100644 index 0000000000..2160c567ee --- /dev/null +++ b/config/alfresco/cluster-context.xml @@ -0,0 +1,18 @@ + + + + + + + + + ${alfresco.cluster.name} + ${alfresco.hazelcast.password} + + + + + + + + \ No newline at end of file diff --git a/config/alfresco/subsystems/fileServers/default/file-servers-context.xml b/config/alfresco/subsystems/fileServers/default/file-servers-context.xml index b1f04b51d1..5cdc9bf594 100644 --- a/config/alfresco/subsystems/fileServers/default/file-servers-context.xml +++ b/config/alfresco/subsystems/fileServers/default/file-servers-context.xml @@ -288,15 +288,7 @@ - - ${filesystem.cluster.enabled} - - - ${filesystem.cluster.name} - - - ${filesystem.cluster.configFile} - + ${filesystem.cluster.debugFlags} diff --git a/config/alfresco/webdav-context.xml b/config/alfresco/webdav-context.xml index da67b8d7bd..6d03787712 100644 --- a/config/alfresco/webdav-context.xml +++ b/config/alfresco/webdav-context.xml @@ -26,22 +26,6 @@ - - - - - - - ${alfresco.cluster.name} - ${alfresco.hazelcast.password} - - - - - - - - \ No newline at end of file diff --git a/source/java/org/alfresco/filesys/config/ClusterConfigBean.java b/source/java/org/alfresco/filesys/config/ClusterConfigBean.java index 3de138f82a..fbec2926a0 100644 --- a/source/java/org/alfresco/filesys/config/ClusterConfigBean.java +++ b/source/java/org/alfresco/filesys/config/ClusterConfigBean.java @@ -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) diff --git a/source/java/org/alfresco/filesys/config/ServerConfigurationBean.java b/source/java/org/alfresco/filesys/config/ServerConfigurationBean.java index 0c1e012afe..dcd7e239ed 100644 --- a/source/java/org/alfresco/filesys/config/ServerConfigurationBean.java +++ b/source/java/org/alfresco/filesys/config/ServerConfigurationBean.java @@ -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); } diff --git a/source/java/org/alfresco/repo/cluster/HazelcastInstanceFactory.java b/source/java/org/alfresco/repo/cluster/HazelcastInstanceFactory.java index a55e6876cb..feb88886aa 100644 --- a/source/java/org/alfresco/repo/cluster/HazelcastInstanceFactory.java +++ b/source/java/org/alfresco/repo/cluster/HazelcastInstanceFactory.java @@ -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. *

* 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. + *

+ * 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(); + } } } diff --git a/source/java/org/alfresco/repo/webdav/LockStoreFactory.java b/source/java/org/alfresco/repo/webdav/LockStoreFactory.java index 207ede744e..85ce0f773c 100644 --- a/source/java/org/alfresco/repo/webdav/LockStoreFactory.java +++ b/source/java/org/alfresco/repo/webdav/LockStoreFactory.java @@ -26,5 +26,5 @@ package org.alfresco.repo.webdav; */ public interface LockStoreFactory { - LockStore getLockStore(); + LockStore createLockStore(); } diff --git a/source/java/org/alfresco/repo/webdav/LockStoreFactoryImpl.java b/source/java/org/alfresco/repo/webdav/LockStoreFactoryImpl.java index bcb63393e6..ea15b79aa1 100644 --- a/source/java/org/alfresco/repo/webdav/LockStoreFactoryImpl.java +++ b/source/java/org/alfresco/repo/webdav/LockStoreFactoryImpl.java @@ -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 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; - } }