diff --git a/config/alfresco/subsystems/fileServers/default/file-servers-context.xml b/config/alfresco/subsystems/fileServers/default/file-servers-context.xml
index 0f10ada890..55bd006d7e 100644
--- a/config/alfresco/subsystems/fileServers/default/file-servers-context.xml
+++ b/config/alfresco/subsystems/fileServers/default/file-servers-context.xml
@@ -288,7 +288,10 @@
${filesystem.cluster.name}
- ${filesystem.cluster.config}
+ ${filesystem.cluster.configFile}
+
+
+ ${filesystem.cluster.debugFlags}
diff --git a/config/alfresco/subsystems/fileServers/default/file-servers.properties b/config/alfresco/subsystems/fileServers/default/file-servers.properties
index 8edf9ab029..20df2642a2 100644
--- a/config/alfresco/subsystems/fileServers/default/file-servers.properties
+++ b/config/alfresco/subsystems/fileServers/default/file-servers.properties
@@ -101,4 +101,11 @@ nfs.mountServerDebug=false
#
filesystem.cluster.enabled=false
filesystem.cluster.name=AlfrescoFilesysCache
-filesystem.cluster.config=Rhubarb
+# Where to find the hazelcast config file
+filesystem.cluster.configFile=not specified
+# Hazelcast cluster debug flags
+# Comma delimeted list of levels
+# "StateCache", "Expire", "NearCache", "Oplock", "ByteLock", "FileAccess", "Membership",
+# "Cleanup", "PerNode", "ClusterEntry", "ClusterMessage", "RemoteTask", "RemoteTiming",
+# "Rename", "FileDataUpdate", "FileStatus"
+filesystem.cluster.debugFlags=
diff --git a/source/java/org/alfresco/filesys/AbstractServerConfigurationBean.java b/source/java/org/alfresco/filesys/AbstractServerConfigurationBean.java
index 3680021153..39871651a4 100644
--- a/source/java/org/alfresco/filesys/AbstractServerConfigurationBean.java
+++ b/source/java/org/alfresco/filesys/AbstractServerConfigurationBean.java
@@ -442,22 +442,6 @@ public abstract class AbstractServerConfigurationBean extends ServerConfiguratio
// Initialize the filesystems
- try
- {
- // Process the Cluster configuration
- processClusterConfig();
-
- // Log the successful startup
-
- // logger.info("JLAN Cluster started");
- }
- catch (Exception ex)
- {
- // Configuration error
-
- logger.error("Cluster configuration error, " + ex.getMessage(), ex);
- }
-
try
{
// Process the core server configuration
@@ -465,6 +449,9 @@ public abstract class AbstractServerConfigurationBean extends ServerConfiguratio
// Process the security configuration
processSecurityConfig();
+
+ // Process the Cluster configuration
+ processClusterConfig();
// Process the filesystems configuration
processFilesystemsConfig();
diff --git a/source/java/org/alfresco/filesys/config/ClusterConfigBean.java b/source/java/org/alfresco/filesys/config/ClusterConfigBean.java
index 5abf68318c..3de138f82a 100644
--- a/source/java/org/alfresco/filesys/config/ClusterConfigBean.java
+++ b/source/java/org/alfresco/filesys/config/ClusterConfigBean.java
@@ -29,6 +29,8 @@ public class ClusterConfigBean
private boolean isClusterEnabled = false;
private String configFile;
private String clusterName;
+ private String debugFlags;
+ private int nearCacheTimeout;
public void setClusterEnabled(boolean clusterEnabled)
{
@@ -59,4 +61,24 @@ public class ClusterConfigBean
{
return configFile;
}
+
+ public void setDebugFlags(String debugFlags)
+ {
+ this.debugFlags = debugFlags;
+ }
+
+ public String getDebugFlags()
+ {
+ return debugFlags;
+ }
+
+ public void setNearCacheTimeout(int nearCacheTimeout)
+ {
+ this.nearCacheTimeout = nearCacheTimeout;
+ }
+
+ public int getNearCacheTimeout()
+ {
+ return nearCacheTimeout;
+ }
}
diff --git a/source/java/org/alfresco/filesys/config/ServerConfigurationBean.java b/source/java/org/alfresco/filesys/config/ServerConfigurationBean.java
index a09209ebea..9a1e375b08 100644
--- a/source/java/org/alfresco/filesys/config/ServerConfigurationBean.java
+++ b/source/java/org/alfresco/filesys/config/ServerConfigurationBean.java
@@ -35,13 +35,11 @@ import java.util.Enumeration;
import java.util.List;
import java.util.StringTokenizer;
-import org.springframework.extensions.config.ConfigElement;
import org.springframework.extensions.config.element.GenericConfigElement;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.filesys.AbstractServerConfigurationBean;
import org.alfresco.filesys.alfresco.AlfrescoContext;
import org.alfresco.filesys.alfresco.ExtendedDiskInterface;
-import org.alfresco.filesys.alfresco.MultiTenantShareMapper;
import org.alfresco.filesys.avm.AVMContext;
import org.alfresco.filesys.avm.AVMDiskDriver;
import org.alfresco.filesys.config.acl.AccessControlListBean;
@@ -1650,12 +1648,24 @@ public class ServerConfigurationBean extends AbstractServerConfigurationBean
ExtendedDiskInterface filesysDriver = getAvmDiskInterface();
DiskDeviceContext diskCtx = (DiskDeviceContext) filesystem;
-
- // Check if the filesystem uses the file state cache, if so then add to the file state reaper
- StandaloneFileStateCache standaloneCache = new StandaloneFileStateCache();
- standaloneCache.initializeCache( new GenericConfigElement( ""), this);
- diskCtx.setStateCache(standaloneCache);
-
+ if(clusterConfigBean != null && clusterConfigBean.getClusterEnabled())
+ {
+ if(logger.isDebugEnabled())
+ {
+ logger.debug("start hazelcast cache : " + clusterConfigBean.getClusterName() + ", shareName: "+ diskCtx.getShareName());
+ }
+ GenericConfigElement hazelConfig = createClusterConfig(diskCtx.getShareName());
+ HazelCastClusterFileStateCache hazel = new HazelCastClusterFileStateCache();
+ hazel.initializeCache(hazelConfig, this);
+ diskCtx.setStateCache(hazel);
+ }
+ else
+ {
+ // Check if the filesystem uses the file state cache, if so then add to the file state reaper
+ StandaloneFileStateCache standaloneCache = new StandaloneFileStateCache();
+ standaloneCache.initializeCache( new GenericConfigElement( ""), this);
+ diskCtx.setStateCache(standaloneCache);
+ }
if ( diskCtx.hasStateCache()) {
// Register the state cache with the reaper thread
@@ -1687,28 +1697,9 @@ public class ServerConfigurationBean extends AbstractServerConfigurationBean
{
logger.debug("start hazelcast cache : " + clusterConfigBean.getClusterName() + ", shareName: "+ filesysContext.getShareName());
}
-
- // initialise the hazelcast cache for this filesystem
+ GenericConfigElement hazelConfig = createClusterConfig(filesysContext.getShareName());
HazelCastClusterFileStateCache hazel = new HazelCastClusterFileStateCache();
- GenericConfigElement config = new GenericConfigElement("hazelcastStateCache");
- GenericConfigElement clusterNameCfg = new GenericConfigElement("clusterName");
- clusterNameCfg.setValue(clusterConfigBean.getClusterName());
- config.addChild(clusterNameCfg);
-
- GenericConfigElement topicNameCfg = new GenericConfigElement("clusterTopic");
- String topicName = filesysContext.getShareName();
- if(topicName == null || topicName.isEmpty())
- {
- topicName="default";
- }
- topicNameCfg.setValue(topicName);
- config.addChild(topicNameCfg);
-
- GenericConfigElement debugCfg = new GenericConfigElement("cacheDebug");
- debugCfg.addAttribute("flags", "StateCache,Rename");
- config.addChild(debugCfg);
-
- hazel.initializeCache(config, this);
+ hazel.initializeCache(hazelConfig, this);
filesysContext.setStateCache(hazel);
}
else
@@ -2175,17 +2166,32 @@ public class ServerConfigurationBean extends AbstractServerConfigurationBean
// Set the state cache, use a hard coded standalone cache for now
FilesystemsConfigSection filesysConfig = (FilesystemsConfigSection) this.getConfigSection( FilesystemsConfigSection.SectionName);
- if ( filesysConfig != null) {
+ if ( filesysConfig != null)
+ {
- try {
-
- // Create a standalone state cache
- StandaloneFileStateCache standaloneCache = new StandaloneFileStateCache();
- standaloneCache.initializeCache( new GenericConfigElement( ""), this);
- filesysConfig.addFileStateCache( diskCtx.getDeviceName(), standaloneCache);
- diskCtx.setStateCache( standaloneCache);
+ try
+ {
+ if(clusterConfigBean != null && clusterConfigBean.getClusterEnabled())
+ {
+ if(logger.isDebugEnabled())
+ {
+ logger.debug("start hazelcast cache : " + clusterConfigBean.getClusterName() + ", shareName: "+ diskCtx.getShareName());
+ }
+ GenericConfigElement hazelConfig = createClusterConfig(diskCtx.getShareName());
+ HazelCastClusterFileStateCache hazel = new HazelCastClusterFileStateCache();
+ hazel.initializeCache(hazelConfig, this);
+ diskCtx.setStateCache(hazel);
+ }
+ else
+ {
+ // Create a standalone state cache
+ StandaloneFileStateCache standaloneCache = new StandaloneFileStateCache();
+ standaloneCache.initializeCache( new GenericConfigElement( ""), this);
+ filesysConfig.addFileStateCache( diskCtx.getDeviceName(), standaloneCache);
+ diskCtx.setStateCache( standaloneCache);
+ }
- FileStateLockManager lockMgr = new FileStateLockManager(standaloneCache);
+ FileStateLockManager lockMgr = new FileStateLockManager(diskCtx.getStateCache());
diskCtx.setLockManager(lockMgr);
diskCtx.setOpLockManager(lockMgr);
}
@@ -2197,43 +2203,22 @@ public class ServerConfigurationBean extends AbstractServerConfigurationBean
}
}
- /**
- * Initialise a runtime context - AVM
- *
- * TODO - what about desktop actions etc?
- *
- * @param diskCtx
- */
- public void initialiseRuntimeContext(AVMContext diskCtx)
- {
- if (diskCtx.getStateCache() == null) {
-
- // Set the state cache, use a hard coded standalone cache for now
- FilesystemsConfigSection filesysConfig = (FilesystemsConfigSection) this.getConfigSection( FilesystemsConfigSection.SectionName);
-
- if ( filesysConfig != null) {
-
- try {
-
- // Create a standalone state cache
- StandaloneFileStateCache standaloneCache = new StandaloneFileStateCache();
- standaloneCache.initializeCache( new GenericConfigElement( ""), this);
- filesysConfig.addFileStateCache( diskCtx.getDeviceName(), standaloneCache);
- diskCtx.setStateCache( standaloneCache);
- }
- catch ( InvalidConfigurationException ex) {
- throw new AlfrescoRuntimeException( "Failed to initialize standalone state cache for " + diskCtx.getDeviceName());
- }
- }
- }
- }
-
@Override
protected void processClusterConfig() throws InvalidConfigurationException
{
-
- // TODO - when should we close the config ? jlanClusterConfig.closeConfig();
+
+// Done by org.alfresco.jlan.server.config.ServerConfiguration.closeConfiguration
+// /**
+// * Close the old hazelcast configuration
+// */
+// ClusterConfigSection secConfig = (ClusterConfigSection) getConfigSection(ClusterConfigSection.SectionName);
+// {
+// if(secConfig != null)
+// {
+// secConfig.closeConfig();
+// }
+// }
if (clusterConfigBean == null || !clusterConfigBean.getClusterEnabled())
{
@@ -2268,4 +2253,38 @@ public class ServerConfigurationBean extends AbstractServerConfigurationBean
throw new InvalidConfigurationException("Unable to start filsystem cluster", e);
}
}
+
+
+ private GenericConfigElement createClusterConfig(String topicName) throws InvalidConfigurationException
+ {
+ GenericConfigElement config = new GenericConfigElement("hazelcastStateCache");
+ GenericConfigElement clusterNameCfg = new GenericConfigElement("clusterName");
+ clusterNameCfg.setValue(clusterConfigBean.getClusterName());
+ config.addChild(clusterNameCfg);
+
+ GenericConfigElement topicNameCfg = new GenericConfigElement("clusterTopic");
+ if(topicName == null || topicName.isEmpty())
+ {
+ topicName="default";
+ }
+ topicNameCfg.setValue(topicName);
+ config.addChild(topicNameCfg);
+
+ if(clusterConfigBean.getDebugFlags() != null)
+ {
+ GenericConfigElement debugCfg = new GenericConfigElement("cacheDebug");
+ debugCfg.addAttribute("flags", clusterConfigBean.getDebugFlags());
+ config.addChild(debugCfg);
+ }
+
+ if(clusterConfigBean.getNearCacheTimeout() > 0)
+ {
+ GenericConfigElement nearCacheCfg = new GenericConfigElement("nearCache");
+ nearCacheCfg.addAttribute("disable", Boolean.FALSE.toString());
+ nearCacheCfg.addAttribute("timeout", Integer.toString(clusterConfigBean.getNearCacheTimeout()));
+ config.addChild(nearCacheCfg);
+ }
+ return config;
+ }
+
}
diff --git a/source/java/org/alfresco/filesys/repo/FilesystemTransactionAdvice.java b/source/java/org/alfresco/filesys/repo/FilesystemTransactionAdvice.java
index ae31252fbf..fdda5a45c2 100644
--- a/source/java/org/alfresco/filesys/repo/FilesystemTransactionAdvice.java
+++ b/source/java/org/alfresco/filesys/repo/FilesystemTransactionAdvice.java
@@ -20,8 +20,9 @@ package org.alfresco.filesys.repo;
import java.io.IOException;
-import org.alfresco.error.AlfrescoRuntimeException;
-import org.alfresco.jlan.server.SrvSession;
+import org.alfresco.jlan.server.core.DeviceContextException;
+import org.alfresco.jlan.server.filesys.IOControlNotImplementedException;
+import org.alfresco.jlan.smb.SMBException;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.transaction.TransactionService;
@@ -29,7 +30,16 @@ import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
/**
- * An advice wrapper for an AlfrescoDiskDriver.
+ * An advice wrapper for an AlfrescoDiskDriver. Wraps the method call with a
+ * RetryingTransactionHandler.
+ *
+ * Needs to let the checked exceptions that are specified on the JLAN interfaces through.
+ * In particular must avoid wrapping JLAN's checked exceptions with an AlfrescoRuntimeException
+ * (so must throw IOException etc)
+ *
+ * @See DiskInterface
+ * @See IOControlHandler
+ *
*/
public class FilesystemTransactionAdvice implements MethodInterceptor
{
@@ -68,11 +78,23 @@ public class FilesystemTransactionAdvice implements MethodInterceptor
{
return methodInvocation.proceed();
}
+ catch (SMBException e)
+ {
+ throw new PropagatingException(e);
+ }
+ catch (IOControlNotImplementedException e)
+ {
+ throw new PropagatingException(e);
+ }
catch (IOException e)
{
// Ensure original checked IOExceptions get propagated
throw new PropagatingException(e);
}
+ catch (DeviceContextException e)
+ {
+ throw new PropagatingException(e);
+ }
}
};
@@ -85,8 +107,17 @@ public class FilesystemTransactionAdvice implements MethodInterceptor
}
catch(PropagatingException pe)
{
- // Unwrap checked exceptions
- throw (IOException) pe.getCause();
+ Throwable t = pe.getCause();
+ if(t != null)
+ {
+ if(t instanceof IOException)
+ {
+ // Unwrap checked exceptions
+ throw (IOException) pe.getCause();
+ }
+ throw t;
+ }
+ throw pe;
}
}
else
@@ -105,16 +136,6 @@ public class FilesystemTransactionAdvice implements MethodInterceptor
}
}
-// public void setDriver(AlfrescoDiskDriver driver)
-// {
-// this.driver = driver;
-// }
-//
-// public AlfrescoDiskDriver getDriver()
-// {
-// return driver;
-// }
-
public void setTransactionService(TransactionService transactionService)
{
this.transactionService = transactionService;