mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-31 17:39:05 +00:00
MNT-24708 - Set messagesCache and loadedBundlesCache as local (#3026)
* In a cluster env these caches were always invalidating the other nodes loaded bundles, forcing them to reload * Only resourceBundlesNamesCache should be invalidating to be able to force the cache reset if a bundle is added, removed or reloaded dynamically * On unregister of a resource bundle, the cache wasn't being explicitly updated, so it was not invalidating the cache on the other nodes.
This commit is contained in:
@@ -1,28 +1,28 @@
|
|||||||
/*
|
/*
|
||||||
* #%L
|
* #%L
|
||||||
* Alfresco Repository
|
* Alfresco Repository
|
||||||
* %%
|
* %%
|
||||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||||
* %%
|
* %%
|
||||||
* This file is part of the Alfresco software.
|
* This file is part of the Alfresco software.
|
||||||
* If the software was purchased under a paid Alfresco license, the terms of
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
* the paid license agreement will prevail. Otherwise, the software is
|
* the paid license agreement will prevail. Otherwise, the software is
|
||||||
* provided under the following open source license terms:
|
* provided under the following open source license terms:
|
||||||
*
|
*
|
||||||
* Alfresco is free software: you can redistribute it and/or modify
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* Alfresco is distributed in the hope that it will be useful,
|
* Alfresco is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU Lesser General Public License for more details.
|
* GNU Lesser General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
package org.alfresco.repo.i18n;
|
package org.alfresco.repo.i18n;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
@@ -204,13 +204,11 @@ public class MessageServiceImpl implements MessageService
|
|||||||
{
|
{
|
||||||
if (! tenantResourceBundleBaseNames.contains(resBundlePath))
|
if (! tenantResourceBundleBaseNames.contains(resBundlePath))
|
||||||
{
|
{
|
||||||
tenantResourceBundleBaseNames.add(resBundlePath);
|
tenantResourceBundleBaseNames.add(resBundlePath);
|
||||||
putResourceBundleBaseNames(tenantDomain, tenantResourceBundleBaseNames);
|
reloadResourceBundles(tenantResourceBundleBaseNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info("Registered message bundle '" + resBundlePath + "'");
|
logger.info("Registered message bundle '" + resBundlePath + "'");
|
||||||
|
|
||||||
clearLoadedResourceBundles(tenantDomain); // force re-load of message cache
|
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -288,61 +286,64 @@ public class MessageServiceImpl implements MessageService
|
|||||||
Map<Locale, Set<String>> loadedResourceBundlesForAllLocales;
|
Map<Locale, Set<String>> loadedResourceBundlesForAllLocales;
|
||||||
Map<Locale, Map<String, String>> cachedMessagesForAllLocales;
|
Map<Locale, Map<String, String>> cachedMessagesForAllLocales;
|
||||||
Set<String> resourceBundleBaseNamesForAllLocales;
|
Set<String> resourceBundleBaseNamesForAllLocales;
|
||||||
|
|
||||||
String tenantDomain = getTenantDomain();
|
String tenantDomain = getTenantDomain();
|
||||||
LockHelper.tryLock(readLock, tryLockTimeout, "getting loaded resource bundles, messages and base names in 'MessageServiceImpl.unregisterResourceBundle()'");
|
LockHelper.tryLock(readLock, tryLockTimeout,
|
||||||
|
"getting loaded resource bundles, messages and base names in 'MessageServiceImpl.unregisterResourceBundle()'");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// all locales
|
// all locales
|
||||||
loadedResourceBundlesForAllLocales = getLoadedResourceBundles(tenantDomain, false);
|
loadedResourceBundlesForAllLocales = getLoadedResourceBundles(tenantDomain, false);
|
||||||
cachedMessagesForAllLocales = getMessages(tenantDomain, false);
|
cachedMessagesForAllLocales = getMessages(tenantDomain, false);
|
||||||
resourceBundleBaseNamesForAllLocales = getResourceBundleBaseNames(tenantDomain, false, true);
|
resourceBundleBaseNamesForAllLocales = getResourceBundleBaseNames(tenantDomain, false, true);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
readLock.unlock();
|
readLock.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
LockHelper.tryLock(writeLock, tryLockTimeout, "removing resource bundle by path in 'MessageServiceImpl.unregisterResourceBundle()'");
|
LockHelper.tryLock(writeLock, tryLockTimeout,
|
||||||
|
"removing resource bundle by path in 'MessageServiceImpl.unregisterResourceBundle()'");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// unload resource bundles for each locale (by tenant, if applicable)
|
// unload resource bundles for each locale (by tenant, if applicable)
|
||||||
if ((loadedResourceBundlesForAllLocales != null) && (cachedMessagesForAllLocales != null))
|
if ((loadedResourceBundlesForAllLocales != null) && (cachedMessagesForAllLocales != null))
|
||||||
{
|
{
|
||||||
Iterator<Locale> itr = loadedResourceBundlesForAllLocales.keySet().iterator();
|
Iterator<Locale> itr = loadedResourceBundlesForAllLocales.keySet().iterator();
|
||||||
|
|
||||||
while (itr.hasNext())
|
while (itr.hasNext())
|
||||||
{
|
{
|
||||||
Locale locale = itr.next();
|
Locale locale = itr.next();
|
||||||
|
|
||||||
Set<String> loadedBundles = loadedResourceBundlesForAllLocales.get(locale);
|
Set<String> loadedBundles = loadedResourceBundlesForAllLocales.get(locale);
|
||||||
Map<String, String> props = cachedMessagesForAllLocales.get(locale);
|
Map<String, String> props = cachedMessagesForAllLocales.get(locale);
|
||||||
|
|
||||||
if ((loadedBundles != null) && (props != null))
|
if ((loadedBundles != null) && (props != null))
|
||||||
{
|
{
|
||||||
if (loadedBundles.contains(resBundlePath))
|
if (loadedBundles.contains(resBundlePath))
|
||||||
{
|
{
|
||||||
ResourceBundle resourcebundle = null;
|
ResourceBundle resourcebundle = null;
|
||||||
|
|
||||||
int idx1 = resBundlePath.indexOf(StoreRef.URI_FILLER);
|
int idx1 = resBundlePath.indexOf(StoreRef.URI_FILLER);
|
||||||
|
|
||||||
if (idx1 != -1)
|
if (idx1 != -1)
|
||||||
{
|
{
|
||||||
// load from repository
|
// load from repository
|
||||||
int idx2 = resBundlePath.indexOf("/", idx1+3);
|
int idx2 = resBundlePath.indexOf("/", idx1 + 3);
|
||||||
|
|
||||||
String store = resBundlePath.substring(0, idx2);
|
String store = resBundlePath.substring(0, idx2);
|
||||||
String path = resBundlePath.substring(idx2);
|
String path = resBundlePath.substring(idx2);
|
||||||
|
|
||||||
StoreRef storeRef = tenantService.getName(new StoreRef(store));
|
StoreRef storeRef = tenantService.getName(new StoreRef(store));
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
resourcebundle = getRepoResourceBundle(storeRef, path, locale);
|
resourcebundle = getRepoResourceBundle(storeRef, path, locale);
|
||||||
}
|
}
|
||||||
catch (IOException ioe)
|
catch (IOException ioe)
|
||||||
{
|
{
|
||||||
throw new AlfrescoRuntimeException("Failed to read message resource bundle from repository " + resBundlePath + " : " + ioe);
|
throw new AlfrescoRuntimeException("Failed to read message resource bundle from repository "
|
||||||
|
+ resBundlePath + " : " + ioe);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -350,7 +351,7 @@ public class MessageServiceImpl implements MessageService
|
|||||||
// load from classpath
|
// load from classpath
|
||||||
resourcebundle = ResourceBundle.getBundle(resBundlePath, locale);
|
resourcebundle = ResourceBundle.getBundle(resBundlePath, locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resourcebundle != null)
|
if (resourcebundle != null)
|
||||||
{
|
{
|
||||||
// unload from the cached messages
|
// unload from the cached messages
|
||||||
@@ -361,21 +362,20 @@ public class MessageServiceImpl implements MessageService
|
|||||||
props.remove(key);
|
props.remove(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
loadedBundles.remove(resBundlePath);
|
loadedBundles.remove(resBundlePath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// unregister resource bundle
|
// unregister resource bundle
|
||||||
if (resourceBundleBaseNamesForAllLocales != null)
|
if (resourceBundleBaseNamesForAllLocales != null)
|
||||||
{
|
{
|
||||||
resourceBundleBaseNamesForAllLocales.remove(resBundlePath);
|
resourceBundleBaseNamesForAllLocales.remove(resBundlePath);
|
||||||
|
reloadResourceBundles(resourceBundleBaseNamesForAllLocales);
|
||||||
logger.info("Unregistered message bundle '" + resBundlePath + "'");
|
logger.info("Unregistered message bundle '" + resBundlePath + "'");
|
||||||
}
|
}
|
||||||
|
|
||||||
clearLoadedResourceBundles(tenantDomain); // force re-load of message cache
|
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -383,6 +383,14 @@ public class MessageServiceImpl implements MessageService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void reloadResourceBundles(Set<String> newResourceBundles)
|
||||||
|
{
|
||||||
|
logger.debug("Reloading message bundles ...");
|
||||||
|
String tenantDomain = getTenantDomain();
|
||||||
|
putResourceBundleBaseNames(tenantDomain, newResourceBundles);
|
||||||
|
clearLoadedResourceBundles(tenantDomain); // force re-load of message cache
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the messages for a locale.
|
* Get the messages for a locale.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -465,7 +473,7 @@ public class MessageServiceImpl implements MessageService
|
|||||||
Set<String> resBundleBaseNames = getResourceBundleBaseNames(tenantDomain, true, false);
|
Set<String> resBundleBaseNames = getResourceBundleBaseNames(tenantDomain, true, false);
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
// load resource bundles for given locale (by tenant, if applicable)
|
// load resource bundles for given locale (by tenant, if applicable)
|
||||||
for (String resBundlePath : resBundleBaseNames)
|
for (String resBundlePath : resBundleBaseNames)
|
||||||
{
|
{
|
||||||
@@ -474,24 +482,25 @@ public class MessageServiceImpl implements MessageService
|
|||||||
ResourceBundle resourcebundle = null;
|
ResourceBundle resourcebundle = null;
|
||||||
|
|
||||||
int idx1 = resBundlePath.indexOf(StoreRef.URI_FILLER);
|
int idx1 = resBundlePath.indexOf(StoreRef.URI_FILLER);
|
||||||
|
|
||||||
if (idx1 != -1)
|
if (idx1 != -1)
|
||||||
{
|
{
|
||||||
// load from repository
|
// load from repository
|
||||||
int idx2 = resBundlePath.indexOf("/", idx1+3);
|
int idx2 = resBundlePath.indexOf("/", idx1 + 3);
|
||||||
|
|
||||||
String store = resBundlePath.substring(0, idx2);
|
String store = resBundlePath.substring(0, idx2);
|
||||||
String path = resBundlePath.substring(idx2);
|
String path = resBundlePath.substring(idx2);
|
||||||
|
|
||||||
StoreRef storeRef = tenantService.getName(new StoreRef(store));
|
StoreRef storeRef = tenantService.getName(new StoreRef(store));
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
resourcebundle = getRepoResourceBundle(storeRef, path, locale);
|
resourcebundle = getRepoResourceBundle(storeRef, path, locale);
|
||||||
}
|
}
|
||||||
catch (IOException ioe)
|
catch (IOException ioe)
|
||||||
{
|
{
|
||||||
throw new AlfrescoRuntimeException("Failed to read message resource bundle from repository " + resBundlePath + " : " + ioe);
|
throw new AlfrescoRuntimeException(
|
||||||
|
"Failed to read message resource bundle from repository " + resBundlePath + " : " + ioe);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -508,13 +517,13 @@ public class MessageServiceImpl implements MessageService
|
|||||||
String key = enumKeys.nextElement();
|
String key = enumKeys.nextElement();
|
||||||
props.put(key, resourcebundle.getString(key));
|
props.put(key, resourcebundle.getString(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
loadedBundles.add(resBundlePath);
|
loadedBundles.add(resBundlePath);
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info("Message bundles (x " + count + ") loaded for locale " + locale);
|
logger.info("Message bundles (x " + count + ") loaded for locale " + locale);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
@@ -394,7 +394,7 @@ cache.loadedResourceBundlesSharedCache.tx.statsEnabled=${caches.tx.statsEnabled}
|
|||||||
cache.loadedResourceBundlesSharedCache.maxItems=1000
|
cache.loadedResourceBundlesSharedCache.maxItems=1000
|
||||||
cache.loadedResourceBundlesSharedCache.timeToLiveSeconds=0
|
cache.loadedResourceBundlesSharedCache.timeToLiveSeconds=0
|
||||||
cache.loadedResourceBundlesSharedCache.maxIdleSeconds=0
|
cache.loadedResourceBundlesSharedCache.maxIdleSeconds=0
|
||||||
cache.loadedResourceBundlesSharedCache.cluster.type=invalidating
|
cache.loadedResourceBundlesSharedCache.cluster.type=local
|
||||||
cache.loadedResourceBundlesSharedCache.backup-count=1
|
cache.loadedResourceBundlesSharedCache.backup-count=1
|
||||||
cache.loadedResourceBundlesSharedCache.eviction-policy=LRU
|
cache.loadedResourceBundlesSharedCache.eviction-policy=LRU
|
||||||
cache.loadedResourceBundlesSharedCache.merge-policy=com.hazelcast.spi.merge.PutIfAbsentMergePolicy
|
cache.loadedResourceBundlesSharedCache.merge-policy=com.hazelcast.spi.merge.PutIfAbsentMergePolicy
|
||||||
@@ -405,7 +405,7 @@ cache.messagesSharedCache.tx.statsEnabled=${caches.tx.statsEnabled}
|
|||||||
cache.messagesSharedCache.maxItems=1000
|
cache.messagesSharedCache.maxItems=1000
|
||||||
cache.messagesSharedCache.timeToLiveSeconds=0
|
cache.messagesSharedCache.timeToLiveSeconds=0
|
||||||
cache.messagesSharedCache.maxIdleSeconds=0
|
cache.messagesSharedCache.maxIdleSeconds=0
|
||||||
cache.messagesSharedCache.cluster.type=invalidating
|
cache.messagesSharedCache.cluster.type=local
|
||||||
cache.messagesSharedCache.backup-count=1
|
cache.messagesSharedCache.backup-count=1
|
||||||
cache.messagesSharedCache.eviction-policy=LRU
|
cache.messagesSharedCache.eviction-policy=LRU
|
||||||
cache.messagesSharedCache.merge-policy=com.hazelcast.spi.merge.PutIfAbsentMergePolicy
|
cache.messagesSharedCache.merge-policy=com.hazelcast.spi.merge.PutIfAbsentMergePolicy
|
||||||
|
Reference in New Issue
Block a user