Merged V3.2 to HEAD

15471: MOB-279: Heartbeat now uses destination URL embedded in the license (if present) and also sends the following new parameters
      - memFree 
      - memMax 
      - memTotal 
      - numUsers (this was there already) 
      - numGroups 
      - repoName 
   15349: Merged V3.1 to V3.2
      15348: Fix ImportTest following fix to ETHREEOH-2219
   15344: Merged V3.1 to V3.2
      15339: ETHREEOH-2219: Give ImporterBootstrap its own retrying transaction helper with specific parameters tuned to its longer-running setup transaction. Should avoid startup errors on clustered installations.


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@16856 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Dave Ward
2009-10-13 11:06:14 +00:00
parent 77ccbfc507
commit e10bf8da0d
6 changed files with 93 additions and 32 deletions

View File

@@ -11,4 +11,11 @@ server.transaction.allow-writes=true
server.transaction.max-retries=40 server.transaction.max-retries=40
server.transaction.min-retry-wait-ms=100 server.transaction.min-retry-wait-ms=100
server.transaction.max-retry-wait-ms=2000 server.transaction.max-retry-wait-ms=2000
server.transaction.wait-increment-ms=100 server.transaction.wait-increment-ms=100
# Values specific to the importer bootstrap on first boot - allow for a
# long-running transaction on one node
server.setup.transaction.max-retries=40
server.setup.transaction.min-retry-wait-ms=15000
server.setup.transaction.max-retry-wait-ms=15000
server.setup.transaction.wait-increment-ms=0

View File

@@ -213,6 +213,9 @@
<property name="transactionService"> <property name="transactionService">
<ref bean="transactionService"/> <ref bean="transactionService"/>
</property> </property>
<property name="retryingTransactionHelper">
<ref bean="storeImporterTransactionHelper"/>
</property>
<property name="nodeService"> <property name="nodeService">
<ref bean="nodeService"/> <ref bean="nodeService"/>
</property> </property>
@@ -238,6 +241,24 @@
<bean id="storeImporterViews" class="org.alfresco.repo.importer.ImporterBootstrapViews" abstract="true"> <bean id="storeImporterViews" class="org.alfresco.repo.importer.ImporterBootstrapViews" abstract="true">
</bean> </bean>
<!-- This retrying transaction helper is tuned for longer-running transactions on initial setup -->
<bean id="storeImporterTransactionHelper" class="org.alfresco.repo.transaction.RetryingTransactionHelper">
<property name="transactionService">
<ref bean="transactionService"/>
</property>
<property name="maxRetries">
<value>${server.setup.transaction.max-retries}</value>
</property>
<property name="minRetryWaitMs">
<value>${server.setup.transaction.min-retry-wait-ms}</value>
</property>
<property name="maxRetryWaitMs">
<value>${server.setup.transaction.max-retry-wait-ms}</value>
</property>
<property name="retryWaitIncrementMs">
<value>${server.setup.transaction.wait-increment-ms}</value>
</property>
</bean>
<!-- --> <!-- -->
<!-- Store specific Importers --> <!-- Store specific Importers -->

View File

@@ -31,6 +31,7 @@ import java.util.Properties;
import org.alfresco.repo.importer.ImporterBootstrap; import org.alfresco.repo.importer.ImporterBootstrap;
import org.alfresco.repo.security.authentication.AuthenticationContext; import org.alfresco.repo.security.authentication.AuthenticationContext;
import org.alfresco.repo.security.authentication.MutableAuthenticationDao; import org.alfresco.repo.security.authentication.MutableAuthenticationDao;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.ServiceRegistry; import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.NodeService;
@@ -110,6 +111,7 @@ public class TestData
bootstrap.setNodeService((NodeService) applicationContext.getBean(ServiceRegistry.NODE_SERVICE.getLocalName())); bootstrap.setNodeService((NodeService) applicationContext.getBean(ServiceRegistry.NODE_SERVICE.getLocalName()));
bootstrap.setNamespaceService((NamespaceService) applicationContext.getBean(ServiceRegistry.NAMESPACE_SERVICE.getLocalName())); bootstrap.setNamespaceService((NamespaceService) applicationContext.getBean(ServiceRegistry.NAMESPACE_SERVICE.getLocalName()));
bootstrap.setTransactionService((TransactionService) applicationContext.getBean(ServiceRegistry.TRANSACTION_SERVICE.getLocalName())); bootstrap.setTransactionService((TransactionService) applicationContext.getBean(ServiceRegistry.TRANSACTION_SERVICE.getLocalName()));
bootstrap.setRetryingTransactionHelper((RetryingTransactionHelper) applicationContext.getBean("storeImporterTransactionHelper"));
bootstrap.setStoreUrl(storeRef.toString()); bootstrap.setStoreUrl(storeRef.toString());
List<Properties> views = new ArrayList<Properties>(); List<Properties> views = new ArrayList<Properties>();

View File

@@ -25,7 +25,6 @@
package org.alfresco.repo.descriptor; package org.alfresco.repo.descriptor;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil;
@@ -42,6 +41,7 @@ import org.alfresco.util.VersionNumber;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationEvent;
import org.springframework.context.ConfigurableApplicationContext;
/** /**
* Implementation of Descriptor Service. * Implementation of Descriptor Service.
@@ -68,7 +68,7 @@ public class DescriptorServiceImpl extends AbstractLifecycleBean implements Desc
/** The heart beat service. */ /** The heart beat service. */
@SuppressWarnings("unused") @SuppressWarnings("unused")
private Object heartBeat; private Object heartBeat;
/** The server descriptor. */ /** The server descriptor. */
private Descriptor serverDescriptor; private Descriptor serverDescriptor;
@@ -128,7 +128,7 @@ public class DescriptorServiceImpl extends AbstractLifecycleBean implements Desc
*/ */
public Descriptor getServerDescriptor() public Descriptor getServerDescriptor()
{ {
return serverDescriptor; return this.serverDescriptor;
} }
/* /*
@@ -137,7 +137,7 @@ public class DescriptorServiceImpl extends AbstractLifecycleBean implements Desc
*/ */
public Descriptor getCurrentRepositoryDescriptor() public Descriptor getCurrentRepositoryDescriptor()
{ {
return currentRepoDescriptor; return this.currentRepoDescriptor;
} }
/* /*
@@ -146,7 +146,7 @@ public class DescriptorServiceImpl extends AbstractLifecycleBean implements Desc
*/ */
public Descriptor getInstalledRepositoryDescriptor() public Descriptor getInstalledRepositoryDescriptor()
{ {
return installedRepoDescriptor; return this.installedRepoDescriptor;
} }
/* /*
@@ -155,7 +155,7 @@ public class DescriptorServiceImpl extends AbstractLifecycleBean implements Desc
*/ */
public LicenseDescriptor getLicenseDescriptor() public LicenseDescriptor getLicenseDescriptor()
{ {
return (licenseService == null) ? null : licenseService.getLicense(); return this.licenseService == null ? null : this.licenseService.getLicense();
} }
/* /*
@@ -165,15 +165,15 @@ public class DescriptorServiceImpl extends AbstractLifecycleBean implements Desc
@Override @Override
protected void onBootstrap(ApplicationEvent event) protected void onBootstrap(ApplicationEvent event)
{ {
// initialise the repository descriptor // Initialize the repository descriptor
// note: this requires that the repository schema has already been initialised // note: this requires that the repository schema has already been initialized
final RetryingTransactionCallback<Descriptor> createDescriptorWork = new RetryingTransactionCallback<Descriptor>() final RetryingTransactionCallback<Descriptor> createDescriptorWork = new RetryingTransactionCallback<Descriptor>()
{ {
public Descriptor execute() throws ClassNotFoundException public Descriptor execute() throws ClassNotFoundException
{ {
boolean initialiseHeartBeat = false; boolean initialiseHeartBeat = false;
// initialise license service (if installed) // Initialize license service (if installed)
DescriptorServiceImpl.this.licenseService = (LicenseService) constructSpecialService("org.alfresco.enterprise.license.LicenseComponent"); DescriptorServiceImpl.this.licenseService = (LicenseService) constructSpecialService("org.alfresco.enterprise.license.LicenseComponent");
if (DescriptorServiceImpl.this.licenseService == null) if (DescriptorServiceImpl.this.licenseService == null)
{ {
@@ -181,12 +181,21 @@ public class DescriptorServiceImpl extends AbstractLifecycleBean implements Desc
initialiseHeartBeat = true; initialiseHeartBeat = true;
} }
// Make the license service available through the application context as a singleton for other beans
// that need it (e.g. the HeartBeat).
ApplicationContext applicationContext = getApplicationContext();
if (applicationContext instanceof ConfigurableApplicationContext)
{
((ConfigurableApplicationContext) applicationContext).getBeanFactory().registerSingleton(
"licenseService", DescriptorServiceImpl.this.licenseService);
}
// verify license, but only if license component is installed // verify license, but only if license component is installed
try try
{ {
licenseService.verifyLicense(); DescriptorServiceImpl.this.licenseService.verifyLicense();
LicenseDescriptor l = licenseService.getLicense(); LicenseDescriptor l = DescriptorServiceImpl.this.licenseService.getLicense();
// Initialise the heartbeat unless it is disabled by the license // Initialize the heartbeat unless it is disabled by the license
if (initialiseHeartBeat || l == null || !l.isHeartBeatDisabled()) if (initialiseHeartBeat || l == null || !l.isHeartBeatDisabled())
{ {
DescriptorServiceImpl.this.heartBeat = constructSpecialService("org.alfresco.enterprise.heartbeat.HeartBeat"); DescriptorServiceImpl.this.heartBeat = constructSpecialService("org.alfresco.enterprise.heartbeat.HeartBeat");
@@ -194,14 +203,14 @@ public class DescriptorServiceImpl extends AbstractLifecycleBean implements Desc
} }
catch (LicenseException e) catch (LicenseException e)
{ {
// Initialise heart beat anyway // Initialize heart beat anyway
DescriptorServiceImpl.this.heartBeat = constructSpecialService("org.alfresco.enterprise.heartbeat.HeartBeat"); DescriptorServiceImpl.this.heartBeat = constructSpecialService("org.alfresco.enterprise.heartbeat.HeartBeat");
throw e; throw e;
} }
// persist the server descriptor values // persist the server descriptor values
currentRepoDescriptor = DescriptorServiceImpl.this.currentRepoDescriptorDAO DescriptorServiceImpl.this.currentRepoDescriptor = DescriptorServiceImpl.this.currentRepoDescriptorDAO
.updateDescriptor(serverDescriptor); .updateDescriptor(DescriptorServiceImpl.this.serverDescriptor);
// create the installed descriptor // create the installed descriptor
Descriptor installed = DescriptorServiceImpl.this.installedRepoDescriptorDAO.getDescriptor(); Descriptor installed = DescriptorServiceImpl.this.installedRepoDescriptorDAO.getDescriptor();
@@ -212,12 +221,12 @@ public class DescriptorServiceImpl extends AbstractLifecycleBean implements Desc
{ {
public Descriptor doWork() throws Exception public Descriptor doWork() throws Exception
{ {
return transactionService.getRetryingTransactionHelper().doInTransaction(createDescriptorWork, return DescriptorServiceImpl.this.transactionService.getRetryingTransactionHelper().doInTransaction(
transactionService.isReadOnly(), false); createDescriptorWork, DescriptorServiceImpl.this.transactionService.isReadOnly(), false);
} }
}, AuthenticationUtil.getSystemUserName()); }, AuthenticationUtil.getSystemUserName());
((ApplicationContext)event.getSource()).publishEvent(new DescriptorServiceAvailableEvent(this)); ((ApplicationContext) event.getSource()).publishEvent(new DescriptorServiceAvailableEvent(this));
} }
/* /*
@@ -242,7 +251,7 @@ public class DescriptorServiceImpl extends AbstractLifecycleBean implements Desc
public void afterPropertiesSet() throws Exception public void afterPropertiesSet() throws Exception
{ {
// initialise server descriptor // initialise server descriptor
serverDescriptor = this.serverDescriptorDAO.getDescriptor(); this.serverDescriptor = this.serverDescriptorDAO.getDescriptor();
} }
/** /**
@@ -498,8 +507,8 @@ public class DescriptorServiceImpl extends AbstractLifecycleBean implements Desc
String label = getVersionLabel(); String label = getVersionLabel();
String build = getVersionBuild(); String build = getVersionBuild();
boolean hasLabel = (label != null && label.length() > 0); boolean hasLabel = label != null && label.length() > 0;
boolean hasBuild = (build != null && build.length() > 0); boolean hasBuild = build != null && build.length() > 0;
// add opening bracket if either a label or build number is present // add opening bracket if either a label or build number is present
if (hasLabel || hasBuild) if (hasLabel || hasBuild)

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2005-2008 Alfresco Software Limited. * Copyright (C) 2005-2009 Alfresco Software Limited.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@@ -18,7 +18,7 @@
* As a special exception to the terms and conditions of version 2.0 of * As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre * the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's * and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing * FLOSS exception. You should have received a copy of the text describing
* the FLOSS exception, and it is also available here: * the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing" * http://www.alfresco.com/legal/licensing"
*/ */
@@ -44,6 +44,7 @@ import org.alfresco.i18n.I18NUtil;
import org.alfresco.repo.security.authentication.AuthenticationContext; import org.alfresco.repo.security.authentication.AuthenticationContext;
import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef; import org.alfresco.service.cmr.repository.StoreRef;
@@ -91,6 +92,7 @@ public class ImporterBootstrap extends AbstractLifecycleBean
private UUID_BINDING uuidBinding = null; private UUID_BINDING uuidBinding = null;
// Dependencies // Dependencies
private TransactionService transactionService; private TransactionService transactionService;
private RetryingTransactionHelper retryingTransactionHelper;
private NamespaceService namespaceService; private NamespaceService namespaceService;
private NodeService nodeService; private NodeService nodeService;
private ImporterService importerService; private ImporterService importerService;
@@ -140,8 +142,8 @@ public class ImporterBootstrap extends AbstractLifecycleBean
public void setUuidBinding(UUID_BINDING uuidBinding) public void setUuidBinding(UUID_BINDING uuidBinding)
{ {
this.uuidBinding = uuidBinding; this.uuidBinding = uuidBinding;
} }
/** /**
* Sets the Transaction Service * Sets the Transaction Service
* *
@@ -151,8 +153,20 @@ public class ImporterBootstrap extends AbstractLifecycleBean
{ {
this.transactionService = transactionService; this.transactionService = transactionService;
} }
/** /**
* Sets the retrying transaction helper specific to the importer bootstrap. This transaction helper's parameters are
* tuned to the longer-running import transaction.
*
* @param retryingTransactionHelper
* the retrying transaction helper
*/
public void setRetryingTransactionHelper(RetryingTransactionHelper retryingTransactionHelper)
{
this.retryingTransactionHelper = retryingTransactionHelper;
}
/**
* Sets the namespace service * Sets the namespace service
* *
* @param namespaceService the namespace service * @param namespaceService the namespace service
@@ -314,6 +328,7 @@ public class ImporterBootstrap extends AbstractLifecycleBean
public void bootstrap() public void bootstrap()
{ {
PropertyCheck.mandatory(this, "transactionService", transactionService); PropertyCheck.mandatory(this, "transactionService", transactionService);
PropertyCheck.mandatory(this, "retryingTransactionHelper", retryingTransactionHelper);
PropertyCheck.mandatory(this, "namespaceService", namespaceService); PropertyCheck.mandatory(this, "namespaceService", namespaceService);
PropertyCheck.mandatory(this, "nodeService", nodeService); PropertyCheck.mandatory(this, "nodeService", nodeService);
PropertyCheck.mandatory(this, "importerService", importerService); PropertyCheck.mandatory(this, "importerService", importerService);
@@ -342,7 +357,7 @@ public class ImporterBootstrap extends AbstractLifecycleBean
return null; return null;
} }
}; };
return transactionService.getRetryingTransactionHelper().doInTransaction(doImportCallback, transactionService.isReadOnly(), false); return retryingTransactionHelper.doInTransaction(doImportCallback, transactionService.isReadOnly(), false);
} }
}; };
AuthenticationUtil.runAs(importRunAs, authenticationContext.getSystemUserName()); AuthenticationUtil.runAs(importRunAs, authenticationContext.getSystemUserName());

View File

@@ -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 * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@@ -18,7 +18,7 @@
* As a special exception to the terms and conditions of version 2.0 of * As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre * the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's * and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing * FLOSS exception. You should have received a copy of the text describing
* the FLOSS exception, and it is also available here: * the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing" * http://www.alfresco.com/legal/licensing"
*/ */
@@ -90,4 +90,11 @@ public interface LicenseDescriptor
* @return <code>true</code> if this license allow the heartbeat to be disabled * @return <code>true</code> if this license allow the heartbeat to be disabled
*/ */
public boolean isHeartBeatDisabled(); public boolean isHeartBeatDisabled();
/**
* Gets an alternative URL that the heart beat should post data to, or <code>null</code> if the default URL is to be used.
*
* @return a URL or <code>null</code>
*/
public String getHeartBeatUrl();
} }