Skip to content

Commit

Permalink
[BACKLOG-5858] Introduce ServiceBarrier backed BarrierBeans
Browse files Browse the repository at this point in the history
Waits for the jcrRepository Bean to be created before starting the the Karaf 2 minute timeout in KarafFeatureWatcherImpl
  • Loading branch information
tkafalas committed Dec 23, 2015
1 parent 6871f17 commit 50ee916
Show file tree
Hide file tree
Showing 10 changed files with 444 additions and 8 deletions.
1 change: 1 addition & 0 deletions api/ivy.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
<dependency org="pentaho" name="pentaho-actionsequence-dom" rev="${dependency.pentaho-actionsequence-dom.revision}" changing="true"/>
<dependency org="pentaho" name="pentaho-xul-core" rev="${dependency.pentaho-xul.revision}" changing="true" transitive="false"/>
<dependency org="pentaho" name="pentaho-database-model" rev="${dependency.pentaho-database-model.revision}" changing="true" transitive="false"/>
<dependency org="pentaho" name="pentaho-service-coordinator" rev="${dependency.pentaho-database-model.revision}" changing="true" transitive="false"/>

<dependency org="junit" name="junit" rev="4.12" conf="test->default"/>
<dependency org="org.mockito" name="mockito-all" rev="1.8.5" conf="test->default"/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
KarafFeatureWatcherBarrier=jcrRepository
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,7 @@ encoding=UTF-8
# change the value for other text directions.
#text-direction=RTL

# This sets the amount of time the system will wait for karaf features to install
# before timing out. Depending on the size of the repository, it may take several
# hours to rebuild Jackrabbit indices. Indices are normally not rebuilt. However,
# indices are always rebuild when 5.X repository is accessed for the first time by
# a 6.X Pentaho Server. If omitted this property defaults to 4 hours.
#karafWaitForBoot = 14400000
# This sets the amount of time the system will wait for karaf to install all of
# it's features before timing out. The default value is 2 minutes but can be
# overridden here.
#karafWaitForBoot = 120000
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,15 @@

package org.pentaho.platform.engine.core.system.objfac.spring;

import java.io.File;

import org.pentaho.platform.engine.core.system.PentahoSystem;
import org.pentaho.platform.engine.core.system.objfac.StandaloneSpringPentahoObjectFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.core.Ordered;
import org.springframework.core.PriorityOrdered;
Expand All @@ -39,6 +40,8 @@
public class ApplicationContextPentahoSystemRegisterer implements ApplicationContextAware, BeanFactoryPostProcessor,
PriorityOrdered {

private static boolean barrierBeanFileProcessed;

@Override
public void setApplicationContext( ApplicationContext applicationContext ) throws BeansException {
safeAddBeanScopePostProcessors( applicationContext );
Expand All @@ -52,7 +55,15 @@ public void setApplicationContext( ApplicationContext applicationContext ) throw
@Override
public void postProcessBeanFactory( ConfigurableListableBeanFactory configurableListableBeanFactory )
throws BeansException {

configurableListableBeanFactory.addBeanPostProcessor( BarrierBeanPostProcessor.getInstance() );
// Make sure barrierbean.xml is processed before any spring processing.
if ( !barrierBeanFileProcessed ) {
// Put ServiceBarrier holds in place
String barrierBeanFilePath =
System.getProperty( "PentahoSystemPath" ) + File.separator + "barrierbean.properties";
BarrierBeanProcessor.getInstance().registerBarrierBeans( barrierBeanFilePath );
barrierBeanFileProcessed = true;
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*!
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* Copyright (c) 2002-2015 Pentaho Corporation.. All rights reserved.
*/
package org.pentaho.platform.engine.core.system.objfac.spring;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
* @author tkafalas
*/
public class BarrierBean {
private String beanName;

public BarrierBean( String beanName ) {
this.beanName = beanName;
}

public String getBeanName() {
return beanName;
}

public static List<BarrierBean> convertString( String barrierBeansString ) {
List<BarrierBean> barrierBeans = Collections.synchronizedList( new ArrayList<BarrierBean>() );
for ( String beanName : barrierBeansString.split( "," ) ) {
barrierBeans.add( new BarrierBean( beanName.trim() ) );
}
return barrierBeans;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*!
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* Copyright (c) 2002-2015 Pentaho Corporation.. All rights reserved.
*/
package org.pentaho.platform.engine.core.system.objfac.spring;

import java.util.Set;

import org.pentaho.platform.servicecoordination.api.IServiceBarrier;
import org.pentaho.platform.servicecoordination.api.IServiceBarrierManager;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

/**
* This class is registered with spring. Spring calls the implemented methods just before, and just after, instantiation
* of a bean.
*
* @author tkafalas
*/
public class BarrierBeanPostProcessor implements BeanPostProcessor {
static IServiceBarrierManager serviceBarrierManager;

private static BarrierBeanPostProcessor barrierBeanPostProcessor;

private BarrierBeanPostProcessor() {
serviceBarrierManager = IServiceBarrierManager.LOCATOR.getManager();
}

public static BarrierBeanPostProcessor getInstance() {
if ( barrierBeanPostProcessor == null ) {
barrierBeanPostProcessor = new BarrierBeanPostProcessor();
}
return barrierBeanPostProcessor;
}

@Override
public Object postProcessBeforeInitialization( Object bean, String beanName ) throws BeansException {
return bean;
}

@Override
/**
* If a bean is initialized that is registered with the {{@link #BarrierBeanProcessor}, then one hold on that
* barrier will be released.
*/
public Object postProcessAfterInitialization( Object bean, String beanName ) throws BeansException {
Set<String> barriers = BarrierBeanProcessor.getInstance().getBeanBarriers().get( beanName );
if ( barriers != null ) {
for ( String barrierName : barriers ) {
IServiceBarrier barrier = serviceBarrierManager.getServiceBarrier( barrierName );
barrier.release();
}
}
return bean;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
/*!
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* Copyright (c) 2002-2015 Pentaho Corporation.. All rights reserved.
*/
package org.pentaho.platform.engine.core.system.objfac.spring;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.collections.ListUtils;
import org.pentaho.platform.servicecoordination.api.IServiceBarrier;
import org.pentaho.platform.servicecoordination.api.IServiceBarrierManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* @author tkafalas
*/
public class BarrierBeanProcessor {
private Logger logger = LoggerFactory.getLogger( BarrierBeanProcessor.class );
private static BarrierBeanProcessor barrierBeanProcessor;

private IServiceBarrierManager serviceBarrierManager = IServiceBarrierManager.LOCATOR.getManager();
private Map<String, List<BarrierBean>> barrierBeans = new ConcurrentHashMap<String, List<BarrierBean>>();
private Map<String, Set<String>> beanBarriers = new ConcurrentHashMap<String, Set<String>>();

private BarrierBeanProcessor() {
}

public static BarrierBeanProcessor getInstance() {
if ( barrierBeanProcessor == null ){
barrierBeanProcessor = new BarrierBeanProcessor();
}
return barrierBeanProcessor;
}

/**
* This method can be run multiple times for multiple barrierBean files. Only one list of barrierBeans is maintained
* so that plugins can add their own barrierBeans if necessary.
*
* @param barrierBeanFilePath
* @return
*/
public void registerBarrierBeans( String barrierBeanFilePath ) {
Properties barrierBeanProperties = new Properties();
File barrierBeanFile = new File( barrierBeanFilePath );
if ( barrierBeanFile.exists() ) {

try {
FileInputStream fileInput = new FileInputStream( barrierBeanFile );
barrierBeanProperties.load( fileInput );
fileInput.close();
} catch ( FileNotFoundException e ) {
e.printStackTrace();
} catch ( IOException e ) {
e.printStackTrace();
}

registerBarrierBeans( barrierBeanProperties );

}
}

/**
* This method can be run multiple times for multiple barrierBean property sets. Only one list of barrierBeans is maintained
* so that plugins can add their own barrierBeans if necessary.
*
* @param barrierBeanFilePath
* @return
*/
@SuppressWarnings( "unchecked" )
public void registerBarrierBeans( Properties barrierBeanProperties ){
Enumeration<Object> enuKeys = barrierBeanProperties.keys();
while ( enuKeys.hasMoreElements() ) {
String barrierName = (String) enuKeys.nextElement();
IServiceBarrier barrier = serviceBarrierManager.getServiceBarrier( barrierName );
List<BarrierBean> theseBarrierBeans =
BarrierBean.convertString( barrierBeanProperties.getProperty( barrierName ) );
if ( theseBarrierBeans.size() > 0 ) {
for ( BarrierBean barrierBean : theseBarrierBeans ) {
//Add the beans/barriers to the maps
if ( beanBarriers.containsKey( barrierBean.getBeanName() ) ) {
beanBarriers.get( barrierBean.getBeanName() ).add( barrierName );
} else {
Set<String> newSet = new HashSet<String>();
newSet.add( barrierName );
beanBarriers.put( barrierBean.getBeanName(), newSet );
}

//put one hold on the barrier for each bean defined for it.
barrier.hold();
}

List<BarrierBean> finalBarrierBeans = (List<BarrierBean>) barrierBeans.get( barrierName );
finalBarrierBeans =
finalBarrierBeans == null ? theseBarrierBeans : ListUtils.union( finalBarrierBeans, theseBarrierBeans );
barrierBeans.put( barrierName, finalBarrierBeans );
}
}
}

/**
* @return Returns a map where key = barrier name, value = list of {@link BarrierBean}s
*/
public Map<String, List<BarrierBean>> getBarrierBeans() {
return barrierBeans;
}

/**
* @return Returns a map where key = Bean Name, value = list of Barrier names
*/
public Map<String, Set<String>> getBeanBarriers() {
return beanBarriers;
}

public void awaitBarrier( String barrierName ){
// Check the service barrier
try {
serviceBarrierManager.getServiceBarrier( barrierName ).awaitAvailability();
} catch ( InterruptedException e1 ) {
// This should never happen
logger.error( "ServiceBarrier Interrupted", e1 );
}
}

}
3 changes: 3 additions & 0 deletions core/test-res/solution/system/barrierBean.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
KarafFeatureWatcherBarrier=jcrRepository
testBarrier2=fee,fi,fo,fum
testBarrier3=fo
Loading

0 comments on commit 50ee916

Please sign in to comment.