diff --git a/config/alfresco/ehcache-default.xml b/config/alfresco/ehcache-default.xml
index a5e893385b..63f4f46e1e 100644
--- a/config/alfresco/ehcache-default.xml
+++ b/config/alfresco/ehcache-default.xml
@@ -354,34 +354,6 @@
overflowToDisk="false"
/>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/source/java/org/alfresco/repo/config/xml/RepoXMLConfigService.java b/source/java/org/alfresco/repo/config/xml/RepoXMLConfigService.java
index 3b925d683e..aec292640f 100644
--- a/source/java/org/alfresco/repo/config/xml/RepoXMLConfigService.java
+++ b/source/java/org/alfresco/repo/config/xml/RepoXMLConfigService.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2007 Alfresco Software Limited.
+ * Copyright (C) 2005-2009 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -71,14 +71,13 @@ public class RepoXMLConfigService extends XMLConfigService implements TenantDepl
private AuthenticationComponent authenticationComponent;
private TenantAdminService tenantAdminService;
- // Internal caches that are clusterable
- private SimpleCache globalConfigCache;
- private SimpleCache> evaluatorsCache;
- private SimpleCache>> sectionsByAreaCache;
- private SimpleCache> sectionsCache;
- private SimpleCache> elementReadersCache;
-
+ // Internal cache (clusterable)
+ private SimpleCache configDataCache;
+ // used to reset the cache
+ private ThreadLocal tenantDomainThreadLocal = new ThreadLocal();
+ private ThreadLocal configDataThreadLocal = new ThreadLocal();
+
public void setTransactionService(TransactionService transactionService)
{
this.transactionService = transactionService;
@@ -94,31 +93,11 @@ public class RepoXMLConfigService extends XMLConfigService implements TenantDepl
this.tenantAdminService = tenantAdminService;
}
- public void setGlobalConfigCache(SimpleCache globalConfigCache)
+ public void setConfigDataCache(SimpleCache configDataCache)
{
- this.globalConfigCache = globalConfigCache;
+ this.configDataCache = configDataCache;
}
-
- public void setEvaluatorsCache(SimpleCache> evaluatorsCache)
- {
- this.evaluatorsCache = evaluatorsCache;
- }
-
- public void setSectionsByAreaCache(SimpleCache>> sectionsByAreaCache)
- {
- this.sectionsByAreaCache = sectionsByAreaCache;
- }
-
- public void setSectionsCache(SimpleCache> sectionsCache)
- {
- this.sectionsCache = sectionsCache;
- }
-
- public void setElementReadersCache(SimpleCache> elementReadersCache)
- {
- this.elementReadersCache = elementReadersCache;
- }
-
+
/**
* Constructs an XMLConfigService using the given config source
@@ -133,7 +112,12 @@ public class RepoXMLConfigService extends XMLConfigService implements TenantDepl
public List initConfig()
{
- List configDeployments = null;
+ return resetRepoConfig().getConfigDeployments();
+ }
+
+ private ConfigData initRepoConfig(String tenantDomain)
+ {
+ ConfigData configData = null;
// can be null e.g. initial login, after fresh bootstrap
String currentUser = authenticationComponent.getCurrentUserName();
@@ -148,9 +132,15 @@ public class RepoXMLConfigService extends XMLConfigService implements TenantDepl
{
userTransaction.begin();
- // parse config and initialise caches
- configDeployments = super.initConfig();
-
+ // parse config
+ List configDeployments = super.initConfig();
+
+ configData = getConfigDataLocal(tenantDomain);
+ if (configData != null)
+ {
+ configData.setConfigDeployments(configDeployments);
+ }
+
userTransaction.commit();
logger.info("Config initialised");
@@ -168,7 +158,7 @@ public class RepoXMLConfigService extends XMLConfigService implements TenantDepl
}
}
- return configDeployments;
+ return configData;
}
public void destroy()
@@ -177,7 +167,76 @@ public class RepoXMLConfigService extends XMLConfigService implements TenantDepl
logger.info("Config destroyed");
}
+
+ /**
+ * Resets the config service
+ */
+ public void reset()
+ {
+ resetRepoConfig();
+ }
+
+ /**
+ * Resets the config service
+ */
+ private ConfigData resetRepoConfig()
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("Resetting repo config service");
+ }
+
+ String tenantDomain = getTenantDomain();
+ try
+ {
+ destroy();
+
+ // create threadlocal, if needed
+ ConfigData configData = getConfigDataLocal(tenantDomain);
+ if (configData == null)
+ {
+ configData = new ConfigData();
+ this.tenantDomainThreadLocal.set(tenantDomain);
+ this.configDataThreadLocal.set(configData);
+ }
+
+ configData = initRepoConfig(tenantDomain);
+
+ if (configData == null)
+ {
+ // unexpected
+ throw new AlfrescoRuntimeException("Failed to reset configData " + tenantDomain);
+ }
+
+ try
+ {
+ writeLock.lock();
+ configDataCache.put(tenantDomain, configData);
+ }
+ finally
+ {
+ writeLock.unlock();
+ }
+ return configData;
+ }
+ finally
+ {
+ try
+ {
+ readLock.lock();
+ if (configDataCache.get(tenantDomain) != null)
+ {
+ this.configDataThreadLocal.set(null); // it's in the cache, clear the threadlocal
+ }
+ }
+ finally
+ {
+ readLock.unlock();
+ }
+ }
+ }
+
@Override
protected void onBootstrap(ApplicationEvent event)
@@ -215,364 +274,230 @@ public class RepoXMLConfigService extends XMLConfigService implements TenantDepl
destroy(); // will be called in context of tenant
}
-
- @Override
- protected ConfigImpl getGlobalConfigImpl()
+ // re-entrant (eg. via reset)
+ private ConfigData getConfigData()
{
String tenantDomain = getTenantDomain();
- ConfigImpl globalConfig = null;
+
+ // check threadlocal first - return if set
+ ConfigData configData = getConfigDataLocal(tenantDomain);
+ if (configData != null)
+ {
+ return configData; // return local config
+ }
+
try
{
+ // check cache second - return if set
readLock.lock();
- globalConfig = globalConfigCache.get(tenantDomain);
+ configData = configDataCache.get(tenantDomain);
+
+ if (configData != null)
+ {
+ return configData; // return cached config
+ }
}
finally
{
readLock.unlock();
- }
+ }
- if (globalConfig == null)
- {
- reset(); // reset caches - may have been invalidated (e.g. in a cluster)
-
- try
- {
- readLock.lock();
- globalConfig = globalConfigCache.get(tenantDomain);
- }
- finally
- {
- readLock.unlock();
- }
-
- if (globalConfig == null)
- {
- // unexpected
- throw new AlfrescoRuntimeException("Failed to reset caches (globalConfigCache) " + tenantDomain);
- }
+ // reset caches - may have been invalidated (e.g. in a cluster)
+ configData = resetRepoConfig();
+
+ if (configData == null)
+ {
+ // unexpected
+ throw new AlfrescoRuntimeException("Failed to get configData " + tenantDomain);
}
- return globalConfig;
- }
+
+ return configData;
+ }
- @Override
- protected void putGlobalConfig(ConfigImpl globalConfig)
+ // get threadlocal
+ private ConfigData getConfigDataLocal(String tenantDomain)
{
+ ConfigData configData = this.configDataThreadLocal.get();
+
+ // check to see if domain switched (eg. during login)
+ if ((configData != null) && (tenantDomain.equals(tenantDomainThreadLocal.get())))
+ {
+ return configData; // return threadlocal, if set
+ }
+
+ return null;
+ }
+
+ private void removeConfigData()
+ {
try
{
- writeLock.lock();
- globalConfigCache.put(getTenantDomain(), globalConfig);
+ writeLock.lock();
+ String tenantDomain = getTenantDomain();
+ if (configDataCache.get(tenantDomain) != null)
+ {
+ configDataCache.remove(tenantDomain);
+ }
}
finally
{
writeLock.unlock();
}
- }
+ }
@Override
+ protected ConfigImpl getGlobalConfigImpl()
+ {
+ return getConfigData().getGlobalConfig();
+ }
+
+ @Override
+ protected void putGlobalConfig(ConfigImpl globalConfig)
+ {
+ getConfigData().setGlobalConfig(globalConfig);
+ }
+
+ @Override
protected void removeGlobalConfig()
{
- try
- {
- writeLock.lock();
- String tenantDomain = getTenantDomain();
- if (globalConfigCache.get(tenantDomain) != null)
- {
- globalConfigCache.remove(tenantDomain);
- }
- }
- finally
- {
- writeLock.unlock();
- }
- }
+ removeConfigData();
+ }
@Override
protected Map getEvaluators()
{
- String tenantDomain = getTenantDomain();
- Map evaluators = null;
- try
- {
- readLock.lock();
- evaluators = evaluatorsCache.get(tenantDomain);
- }
- finally
- {
- readLock.unlock();
- }
-
- if (evaluators == null)
- {
- reset(); // reset caches - may have been invalidated (e.g. in a cluster)
-
- try
- {
- readLock.lock();
- evaluators = evaluatorsCache.get(tenantDomain);
- }
- finally
- {
- readLock.unlock();
- }
-
- if (evaluators == null)
- {
- // unexpected
- throw new AlfrescoRuntimeException("Failed to reset caches (evaluatorsCache) " + tenantDomain);
- }
- }
- return evaluators;
- }
+ return getConfigData().getEvaluators();
+ }
@Override
protected void putEvaluators(Map evaluators)
{
- try
- {
- writeLock.lock();
- evaluatorsCache.put(getTenantDomain(), evaluators);
- }
- finally
- {
- writeLock.unlock();
- }
- }
-
+ getConfigData().setEvaluators(evaluators);
+ }
+
@Override
protected void removeEvaluators()
{
- try
- {
- writeLock.lock();
- String tenantDomain = getTenantDomain();
- if (evaluatorsCache.get(tenantDomain) != null)
- {
- evaluatorsCache.get(tenantDomain).clear();
- evaluatorsCache.remove(tenantDomain);
- }
- }
- finally
- {
- writeLock.unlock();
- }
- }
+ removeConfigData();
+ }
@Override
protected Map> getSectionsByArea()
{
- String tenantDomain = getTenantDomain();
- Map> sectionsByArea = null;
- try
- {
- readLock.lock();
- sectionsByArea = sectionsByAreaCache.get(tenantDomain);
- }
- finally
- {
- readLock.unlock();
- }
-
- if (sectionsByArea == null)
- {
- reset(); // reset caches - may have been invalidated (e.g. in a cluster)
-
- try
- {
- readLock.lock();
- sectionsByArea = sectionsByAreaCache.get(tenantDomain);
- }
- finally
- {
- readLock.unlock();
- }
-
- if (sectionsByArea == null)
- {
- // unexpected
- throw new AlfrescoRuntimeException("Failed to reset caches (sectionsByAreaCache) " + tenantDomain);
- }
- }
- return sectionsByArea;
- }
+ return getConfigData().getSectionsByArea();
+ }
@Override
protected void putSectionsByArea(Map> sectionsByArea)
{
- try
- {
- writeLock.lock();
- sectionsByAreaCache.put(getTenantDomain(), sectionsByArea);
- }
- finally
- {
- writeLock.unlock();
- }
- }
-
+ getConfigData().setSectionsByArea(sectionsByArea);
+ }
+
@Override
protected void removeSectionsByArea()
{
- try
- {
- writeLock.lock();
- String tenantDomain = getTenantDomain();
- if (sectionsByAreaCache.get(tenantDomain) != null)
- {
- sectionsByAreaCache.get(tenantDomain).clear();
- sectionsByAreaCache.remove(tenantDomain);
- }
- }
- finally
- {
- writeLock.unlock();
- }
- }
+ removeConfigData();
+ }
@Override
protected List getSections()
{
- String tenantDomain = getTenantDomain();
- List sections = null;
- try
- {
- readLock.lock();
- sections = sectionsCache.get(tenantDomain);
- }
- finally
- {
- readLock.unlock();
- }
-
- if (sections == null)
- {
- reset(); // reset caches - may have been invalidated (e.g. in a cluster)
-
- try
- {
- readLock.lock();
- sections = sectionsCache.get(tenantDomain);
- }
- finally
- {
- readLock.unlock();
- }
-
- if (sections == null)
- {
- // unexpected
- throw new AlfrescoRuntimeException("Failed to reset caches (sectionsCache) " + tenantDomain);
- }
- }
- return sections;
- }
+ return getConfigData().getSections();
+ }
@Override
protected void putSections(List sections)
{
- try
- {
- writeLock.lock();
- sectionsCache.put(getTenantDomain(), sections);
- }
- finally
- {
- writeLock.unlock();
- }
- }
-
+ getConfigData().setSections(sections);
+ }
+
@Override
protected void removeSections()
{
- try
- {
- writeLock.lock();
- String tenantDomain = getTenantDomain();
- if (sectionsCache.get(tenantDomain) != null)
- {
- sectionsCache.get(tenantDomain).clear();
- sectionsCache.remove(tenantDomain);
- }
- }
- finally
- {
- writeLock.unlock();
- }
- }
+ removeConfigData();
+ }
@Override
protected Map getElementReaders()
{
- String tenantDomain = getTenantDomain();
- Map elementReaders = null;
- try
- {
- readLock.lock();
- elementReaders = elementReadersCache.get(tenantDomain);
- }
- finally
- {
- readLock.unlock();
- }
-
- if (elementReaders == null)
- {
- reset(); // reset caches - may have been invalidated (e.g. in a cluster)
-
- try
- {
- readLock.lock();
- elementReaders = elementReadersCache.get(tenantDomain);
- }
- finally
- {
- readLock.unlock();
- }
-
- if (elementReaders == null)
- {
- // unexpected
- throw new AlfrescoRuntimeException("Failed to reset caches (elementReadersCache) " + tenantDomain);
- }
- }
- return elementReaders;
- }
+ return getConfigData().getElementReaders();
+ }
@Override
- protected void putElementReaders(Map elementReader)
+ protected void putElementReaders(Map elementReaders)
{
- try
- {
- writeLock.lock();
- elementReadersCache.put(getTenantDomain(), elementReader);
- }
- finally
- {
- writeLock.unlock();
- }
- }
-
+ getConfigData().setElementReaders(elementReaders);
+ }
+
@Override
protected void removeElementReaders()
{
- try
- {
- writeLock.lock();
- String tenantDomain = getTenantDomain();
- if (elementReadersCache.get(tenantDomain) != null)
- {
- elementReadersCache.get(tenantDomain).clear();
- elementReadersCache.remove(tenantDomain);
- }
- }
- finally
- {
- writeLock.unlock();
- }
- }
+ removeConfigData();
+ }
// local helper - returns tenant domain (or empty string if default non-tenant)
private String getTenantDomain()
{
return tenantAdminService.getCurrentUserDomain();
}
+
+ private class ConfigData
+ {
+ private ConfigImpl globalConfig;
+ private Map evaluators;
+ private Map> sectionsByArea;
+ private List sections;
+ private Map elementReaders;
+
+ private List configDeployments;
+
+ public ConfigImpl getGlobalConfig()
+ {
+ return globalConfig;
+ }
+ public void setGlobalConfig(ConfigImpl globalConfig)
+ {
+ this.globalConfig = globalConfig;
+ }
+ public Map getEvaluators()
+ {
+ return evaluators;
+ }
+ public void setEvaluators(Map evaluators)
+ {
+ this.evaluators = evaluators;
+ }
+ public Map> getSectionsByArea()
+ {
+ return sectionsByArea;
+ }
+ public void setSectionsByArea(Map> sectionsByArea)
+ {
+ this.sectionsByArea = sectionsByArea;
+ }
+ public List getSections()
+ {
+ return sections;
+ }
+ public void setSections(List sections)
+ {
+ this.sections = sections;
+ }
+ public Map getElementReaders()
+ {
+ return elementReaders;
+ }
+ public void setElementReaders(Map elementReaders)
+ {
+ this.elementReaders = elementReaders;
+ }
+ public List getConfigDeployments()
+ {
+ return configDeployments;
+ }
+ public void setConfigDeployments(List configDeployments)
+ {
+ this.configDeployments = configDeployments;
+ }
+ }
}