Author: bdelacretaz
Date: Fri Jul 10 16:21:25 2009
New Revision: 793010
URL: http://svn.apache.org/viewvc?rev=793010&view=rev
Log:
SLING-1042 - Optimize jcrinstall retry cycles
Added:
sling/trunk/contrib/extensions/jcrinstall/osgi/src/main/java/org/apache/sling/osgi/installer/OsgiControllerStatistics.java
(with props)
sling/trunk/contrib/extensions/jcrinstall/osgi/src/main/java/org/apache/sling/osgi/installer/impl/EventsCounter.java
(with props)
sling/trunk/contrib/extensions/jcrinstall/osgi/src/main/java/org/apache/sling/osgi/installer/impl/EventsCounterImpl.java
(with props)
Modified:
sling/trunk/contrib/extensions/jcrinstall/it/src/test/java/org/apache/sling/jcr/jcrinstall/it/OsgiControllerTest.java
sling/trunk/contrib/extensions/jcrinstall/osgi/src/main/java/org/apache/sling/osgi/installer/impl/Activator.java
sling/trunk/contrib/extensions/jcrinstall/osgi/src/main/java/org/apache/sling/osgi/installer/impl/OsgiControllerImpl.java
sling/trunk/contrib/extensions/jcrinstall/osgi/src/main/java/org/apache/sling/osgi/installer/impl/OsgiControllerTask.java
sling/trunk/contrib/extensions/jcrinstall/osgi/src/main/java/org/apache/sling/osgi/installer/impl/tasks/BundleStartTask.java
Modified:
sling/trunk/contrib/extensions/jcrinstall/it/src/test/java/org/apache/sling/jcr/jcrinstall/it/OsgiControllerTest.java
URL:
http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/jcrinstall/it/src/test/java/org/apache/sling/jcr/jcrinstall/it/OsgiControllerTest.java?rev=793010&r1=793009&r2=793010&view=diff
==============================================================================
---
sling/trunk/contrib/extensions/jcrinstall/it/src/test/java/org/apache/sling/jcr/jcrinstall/it/OsgiControllerTest.java
(original)
+++
sling/trunk/contrib/extensions/jcrinstall/it/src/test/java/org/apache/sling/jcr/jcrinstall/it/OsgiControllerTest.java
Fri Jul 10 16:21:25 2009
@@ -30,12 +30,15 @@
import static org.ops4j.pax.exam.container.def.PaxRunnerOptions.vmOption;
import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
import java.util.Dictionary;
import java.util.Hashtable;
import org.apache.sling.osgi.installer.DictionaryInstallableData;
import org.apache.sling.osgi.installer.OsgiController;
import org.apache.sling.osgi.installer.OsgiControllerServices;
+import org.apache.sling.osgi.installer.OsgiControllerStatistics;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.Inject;
@@ -43,9 +46,12 @@
import org.ops4j.pax.exam.junit.JUnit4TestRunner;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkEvent;
+import org.osgi.framework.FrameworkListener;
import org.osgi.framework.ServiceReference;
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.packageadmin.PackageAdmin;
/** Test the OsgiController running in the OSGi framework
*
@@ -55,9 +61,10 @@
*
*/
@RunWith(JUnit4TestRunner.class)
-public class OsgiControllerTest {
+public class OsgiControllerTest implements FrameworkListener {
public final static String POM_VERSION =
System.getProperty("jcrinstall.pom.version");
public final static String JAR_EXT = ".jar";
+ private int packageRefreshEventsCount;
@Inject
protected BundleContext bundleContext;
@@ -71,6 +78,61 @@
return result;
}
+ protected void generateBundleEvent() throws Exception {
+ // install a bundle manually to generate a bundle event
+ final File f = getTestBundle("org.apache.sling.jcr.jcrinstall.it-" +
POM_VERSION + "-testbundle-1.0.jar");
+ final InputStream is = new FileInputStream(f);
+ Bundle b = null;
+ try {
+ b = bundleContext.installBundle(getClass().getName(), is);
+ b.start();
+ final long timeout = System.currentTimeMillis() + 2000L;
+ while(b.getState() != Bundle.ACTIVE && System.currentTimeMillis()
< timeout) {
+ Thread.sleep(10L);
+ }
+ } finally {
+ if(is != null) {
+ is.close();
+ }
+ if(b != null) {
+ b.uninstall();
+ }
+ }
+ }
+
+ public void frameworkEvent(FrameworkEvent event) {
+ if (event.getType() == FrameworkEvent.PACKAGES_REFRESHED) {
+ packageRefreshEventsCount++;
+ }
+ }
+
+ protected void refreshPackages() {
+ bundleContext.addFrameworkListener(this);
+ final int MAX_REFRESH_PACKAGES_WAIT_SECONDS = 5;
+ final int targetEventCount = packageRefreshEventsCount + 1;
+ final long timeout = System.currentTimeMillis() +
MAX_REFRESH_PACKAGES_WAIT_SECONDS * 1000L;
+
+ final PackageAdmin pa = getService(PackageAdmin.class);
+ pa.refreshPackages(null);
+
+ try {
+ while(true) {
+ if(System.currentTimeMillis() > timeout) {
+ break;
+ }
+ if(packageRefreshEventsCount >= targetEventCount) {
+ break;
+ }
+ try {
+ Thread.sleep(250L);
+ } catch(InterruptedException ignore) {
+ }
+ }
+ } finally {
+ bundleContext.removeFrameworkListener(this);
+ }
+ }
+
protected Configuration findConfiguration(String pid) throws Exception {
final ConfigurationAdmin ca = getService(ConfigurationAdmin.class);
if(ca != null) {
@@ -311,6 +373,50 @@
assertFalse(needsB + " must not be started, testB not present",
b.getState() == Bundle.ACTIVE);
}
+ // Check SLING-1042 retry rules
+ assertTrue("OsgiController must implement OsgiControllerStatistics", c
instanceof OsgiControllerStatistics);
+ final OsgiControllerStatistics stats = (OsgiControllerStatistics)c;
+
+ {
+ long n = stats.getExecutedTasksCount();
+ c.executeScheduledOperations();
+ assertTrue("First retry must not wait for an event",
stats.getExecutedTasksCount() > n);
+ n = stats.getExecutedTasksCount();
+ c.executeScheduledOperations();
+ assertEquals("Retrying before a bundle event happens must not
execute any OsgiControllerTask", n, stats.getExecutedTasksCount());
+
+ n = stats.getExecutedTasksCount();
+ generateBundleEvent();
+ c.executeScheduledOperations();
+ assertTrue("Retrying after a bundle event must execute at least
one OsgiControllerTask", stats.getExecutedTasksCount() > n);
+ }
+
+ {
+ // wait until no more events are received
+ final long timeout = System.currentTimeMillis() + 2000L;
+ while(System.currentTimeMillis() < timeout) {
+ final long n = stats.getExecutedTasksCount();
+ c.executeScheduledOperations();
+ if(n == stats.getExecutedTasksCount()) {
+ break;
+ }
+ Thread.sleep(10L);
+ }
+
+ if(System.currentTimeMillis() >= timeout) {
+ fail("Retries did not stop within specified time");
+ }
+ }
+
+ {
+ long n = stats.getExecutedTasksCount();
+ c.executeScheduledOperations();
+ assertEquals("Retrying before a framework event happens must not
execute any OsgiControllerTask", n, stats.getExecutedTasksCount());
+ refreshPackages();
+ c.executeScheduledOperations();
+ assertTrue("Retrying after framework event must execute at least
one OsgiControllerTask", stats.getExecutedTasksCount() > n);
+ }
+
// now install testB -> needsB must start
{
c.scheduleInstallOrUpdate(testB + JAR_EXT,
Added:
sling/trunk/contrib/extensions/jcrinstall/osgi/src/main/java/org/apache/sling/osgi/installer/OsgiControllerStatistics.java
URL:
http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/jcrinstall/osgi/src/main/java/org/apache/sling/osgi/installer/OsgiControllerStatistics.java?rev=793010&view=auto
==============================================================================
---
sling/trunk/contrib/extensions/jcrinstall/osgi/src/main/java/org/apache/sling/osgi/installer/OsgiControllerStatistics.java
(added)
+++
sling/trunk/contrib/extensions/jcrinstall/osgi/src/main/java/org/apache/sling/osgi/installer/OsgiControllerStatistics.java
Fri Jul 10 16:21:25 2009
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.osgi.installer;
+
+/** Statistics for the OsgiController */
+public interface OsgiControllerStatistics {
+ /** How many OsgiControllerTask the controller tried to execute */
+ long getExecutedTasksCount();
+}
Propchange:
sling/trunk/contrib/extensions/jcrinstall/osgi/src/main/java/org/apache/sling/osgi/installer/OsgiControllerStatistics.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
sling/trunk/contrib/extensions/jcrinstall/osgi/src/main/java/org/apache/sling/osgi/installer/OsgiControllerStatistics.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision Rev URL
Modified:
sling/trunk/contrib/extensions/jcrinstall/osgi/src/main/java/org/apache/sling/osgi/installer/impl/Activator.java
URL:
http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/jcrinstall/osgi/src/main/java/org/apache/sling/osgi/installer/impl/Activator.java?rev=793010&r1=793009&r2=793010&view=diff
==============================================================================
---
sling/trunk/contrib/extensions/jcrinstall/osgi/src/main/java/org/apache/sling/osgi/installer/impl/Activator.java
(original)
+++
sling/trunk/contrib/extensions/jcrinstall/osgi/src/main/java/org/apache/sling/osgi/installer/impl/Activator.java
Fri Jul 10 16:21:25 2009
@@ -39,14 +39,12 @@
private static String LOG_SERVICE_NAME = LogService.class.getName();
private ServiceTracker startLevelTracker;
-
private ServiceTracker packageAdminTracker;
-
private ServiceTracker logServiceTracker;
-
- private OsgiControllerImpl service;
-
- private ServiceRegistration serviceReg;
+ private OsgiControllerImpl osgiControllerService;
+ private ServiceRegistration osgiControllerServiceReg;
+ private EventsCounterImpl eventsCounter;
+ private ServiceRegistration eventsCounterServiceReg;
/**
* @see
org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
@@ -59,21 +57,36 @@
this.packageAdminTracker.open();
this.logServiceTracker.open();
- // register service
- final Hashtable<String, String> props = new Hashtable<String,
String>();
- props.put(Constants.SERVICE_DESCRIPTION, "Apache Sling Install
Controller Service");
- props.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation");
+ // register OsgiController service
+ {
+ final Hashtable<String, String> props = new Hashtable<String,
String>();
+ props.put(Constants.SERVICE_DESCRIPTION, "Apache Sling Install
Controller Service");
+ props.put(Constants.SERVICE_VENDOR, "The Apache Software
Foundation");
+
+ // Assume PackageAdmin is available before this bundle is started.
+ // That's the case when using Felix OSGi, not sure about other
frameworks.
+ this.osgiControllerService = new OsgiControllerImpl(context,
+
(PackageAdmin)checkNotNull(this.packageAdminTracker.getService(),
"PackageAdmin"),
+ logServiceTracker);
+ final String [] serviceInterfaces = {
+ OsgiController.class.getName(),
+ OsgiControllerServices.class.getName()
+ };
+ osgiControllerServiceReg =
context.registerService(serviceInterfaces, osgiControllerService, props);
+ }
- // Assume PackageAdmin is available before this bundle is started.
- // That's the case when using Felix OSGi, not sure about other
frameworks.
- this.service = new OsgiControllerImpl(context,
-
(PackageAdmin)checkNotNull(this.packageAdminTracker.getService(),
"PackageAdmin"),
- logServiceTracker);
- final String [] serviceInterfaces = {
- OsgiController.class.getName(),
- OsgiControllerServices.class.getName()
- };
- serviceReg = context.registerService(serviceInterfaces, service,
props);
+ // register EventsCounter service
+ {
+ final Hashtable<String, String> props = new Hashtable<String,
String>();
+ props.put(Constants.SERVICE_DESCRIPTION, "Apache Sling
EventsCounter Service");
+ props.put(Constants.SERVICE_VENDOR, "The Apache Software
Foundation");
+
+ this.eventsCounter = new EventsCounterImpl(context);
+ final String [] serviceInterfaces = {
+ EventsCounter.class.getName()
+ };
+ eventsCounterServiceReg =
context.registerService(serviceInterfaces, eventsCounter, props);
+ }
}
/** Complain if value is null */
@@ -88,13 +101,21 @@
* @see
org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
*/
public void stop(BundleContext context) throws Exception {
- if ( this.serviceReg != null ) {
- this.serviceReg.unregister();
- this.serviceReg = null;
- }
- if ( this.service != null ) {
- this.service.deactivate();
- this.service = null;
+ if( this.eventsCounterServiceReg != null) {
+ this.eventsCounterServiceReg.unregister();
+ this.eventsCounterServiceReg = null;
+ }
+ if( this.eventsCounter != null) {
+ this.eventsCounter.deactivate();
+ this.eventsCounter = null;
+ }
+ if ( this.osgiControllerServiceReg != null ) {
+ this.osgiControllerServiceReg.unregister();
+ this.osgiControllerServiceReg = null;
+ }
+ if ( this.osgiControllerService != null ) {
+ this.osgiControllerService.deactivate();
+ this.osgiControllerService = null;
}
if ( this.startLevelTracker != null ) {
this.startLevelTracker.close();
Added:
sling/trunk/contrib/extensions/jcrinstall/osgi/src/main/java/org/apache/sling/osgi/installer/impl/EventsCounter.java
URL:
http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/jcrinstall/osgi/src/main/java/org/apache/sling/osgi/installer/impl/EventsCounter.java?rev=793010&view=auto
==============================================================================
---
sling/trunk/contrib/extensions/jcrinstall/osgi/src/main/java/org/apache/sling/osgi/installer/impl/EventsCounter.java
(added)
+++
sling/trunk/contrib/extensions/jcrinstall/osgi/src/main/java/org/apache/sling/osgi/installer/impl/EventsCounter.java
Fri Jul 10 16:21:25 2009
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.osgi.installer.impl;
+
+/** Count framework + bundle events - used for SLING-1042 retries optimization
*/
+public interface EventsCounter {
+ long getTotalEventsCount();
+}
Propchange:
sling/trunk/contrib/extensions/jcrinstall/osgi/src/main/java/org/apache/sling/osgi/installer/impl/EventsCounter.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
sling/trunk/contrib/extensions/jcrinstall/osgi/src/main/java/org/apache/sling/osgi/installer/impl/EventsCounter.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision Rev URL
Added:
sling/trunk/contrib/extensions/jcrinstall/osgi/src/main/java/org/apache/sling/osgi/installer/impl/EventsCounterImpl.java
URL:
http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/jcrinstall/osgi/src/main/java/org/apache/sling/osgi/installer/impl/EventsCounterImpl.java?rev=793010&view=auto
==============================================================================
---
sling/trunk/contrib/extensions/jcrinstall/osgi/src/main/java/org/apache/sling/osgi/installer/impl/EventsCounterImpl.java
(added)
+++
sling/trunk/contrib/extensions/jcrinstall/osgi/src/main/java/org/apache/sling/osgi/installer/impl/EventsCounterImpl.java
Fri Jul 10 16:21:25 2009
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.osgi.installer.impl;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.BundleListener;
+import org.osgi.framework.FrameworkEvent;
+import org.osgi.framework.FrameworkListener;
+
+/** EventsCounter implementation - simply counts events,
+ * to avoid having to make each BundleStartTask that's
+ * waiting for retries a FrameworkListener and BundleListener
+ */
+class EventsCounterImpl implements EventsCounter, FrameworkListener,
BundleListener {
+ private long eventsCount;
+ private final BundleContext bundleContext;
+
+ EventsCounterImpl(BundleContext bc) {
+ this.bundleContext = bc;
+ bundleContext.addBundleListener(this);
+ bundleContext.addFrameworkListener(this);
+ }
+
+ void deactivate() {
+ bundleContext.removeBundleListener(this);
+ bundleContext.removeFrameworkListener(this);
+ }
+
+ public long getTotalEventsCount() {
+ return eventsCount;
+ }
+
+ public void frameworkEvent(FrameworkEvent arg0) {
+ // we'll retry as soon as any FrameworkEvent or BundleEvent happens
+ eventsCount++;
+ }
+
+ public void bundleChanged(BundleEvent arg0) {
+ // we'll retry as soon as any FrameworkEvent or BundleEvent happens
+ eventsCount++;
+ }
+}
Propchange:
sling/trunk/contrib/extensions/jcrinstall/osgi/src/main/java/org/apache/sling/osgi/installer/impl/EventsCounterImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
sling/trunk/contrib/extensions/jcrinstall/osgi/src/main/java/org/apache/sling/osgi/installer/impl/EventsCounterImpl.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision Rev URL
Modified:
sling/trunk/contrib/extensions/jcrinstall/osgi/src/main/java/org/apache/sling/osgi/installer/impl/OsgiControllerImpl.java
URL:
http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/jcrinstall/osgi/src/main/java/org/apache/sling/osgi/installer/impl/OsgiControllerImpl.java?rev=793010&r1=793009&r2=793010&view=diff
==============================================================================
---
sling/trunk/contrib/extensions/jcrinstall/osgi/src/main/java/org/apache/sling/osgi/installer/impl/OsgiControllerImpl.java
(original)
+++
sling/trunk/contrib/extensions/jcrinstall/osgi/src/main/java/org/apache/sling/osgi/installer/impl/OsgiControllerImpl.java
Fri Jul 10 16:21:25 2009
@@ -29,6 +29,7 @@
import org.apache.sling.osgi.installer.JcrInstallException;
import org.apache.sling.osgi.installer.OsgiController;
import org.apache.sling.osgi.installer.OsgiControllerServices;
+import org.apache.sling.osgi.installer.OsgiControllerStatistics;
import org.apache.sling.osgi.installer.ResourceOverrideRules;
import org.apache.sling.osgi.installer.impl.tasks.BundleInstallRemoveTask;
import org.apache.sling.osgi.installer.impl.tasks.ConfigInstallRemoveTask;
@@ -46,7 +47,8 @@
public class OsgiControllerImpl
implements OsgiController,
OsgiControllerServices,
- OsgiControllerTaskContext {
+ OsgiControllerTaskContext,
+ OsgiControllerStatistics {
private final BundleContext bundleContext;
private final Storage storage;
@@ -59,6 +61,7 @@
private final ServiceTracker logServiceTracker;
private int threadCounter;
private final PackageAdmin packageAdmin;
+ private int executedTasksCount;
public static final String BUNDLE_EXTENSION = ".jar";
public static final String STORAGE_FILENAME = "controller.storage";
@@ -144,9 +147,28 @@
if(tasks.isEmpty()) {
return;
}
-
+
+ // No executable tasks?
+ boolean exec = false;
+ synchronized (tasks) {
+ for(OsgiControllerTask t : tasks) {
+ if(t.isExecutable(this)) {
+ exec = true;
+ break;
+ }
+ }
+ }
+
if(getLogService() != null) {
- getLogService().log(LogService.LOG_INFO,
"executeScheduledOperations() starts");
+ if(exec) {
+ getLogService().log(LogService.LOG_INFO,
"executeScheduledOperations() starts");
+ } else {
+ getLogService().log(LogService.LOG_DEBUG, "No executable
tasks, nothing to do");
+ }
+ }
+
+ if(!exec) {
+ return;
}
synchronized (tasks) {
@@ -199,6 +221,7 @@
final List<OsgiControllerTask> toRemove
= new LinkedList<OsgiControllerTask>();
for(OsgiControllerTask t : tasks) {
toRemove.add(t);
+ executedTasksCount++;
executeTask(t);
if(!tasksForThisCycle.isEmpty()) {
break;
@@ -272,4 +295,7 @@
return this;
}
+ public long getExecutedTasksCount() {
+ return executedTasksCount;
+ }
}
\ No newline at end of file
Modified:
sling/trunk/contrib/extensions/jcrinstall/osgi/src/main/java/org/apache/sling/osgi/installer/impl/OsgiControllerTask.java
URL:
http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/jcrinstall/osgi/src/main/java/org/apache/sling/osgi/installer/impl/OsgiControllerTask.java?rev=793010&r1=793009&r2=793010&view=diff
==============================================================================
---
sling/trunk/contrib/extensions/jcrinstall/osgi/src/main/java/org/apache/sling/osgi/installer/impl/OsgiControllerTask.java
(original)
+++
sling/trunk/contrib/extensions/jcrinstall/osgi/src/main/java/org/apache/sling/osgi/installer/impl/OsgiControllerTask.java
Fri Jul 10 16:21:25 2009
@@ -26,9 +26,15 @@
/** Tasks are sorted according to this key */
public abstract String getSortKey();
+ /** All comparisons are based on getSortKey() */
public final int compareTo(OsgiControllerTask o) {
return getSortKey().compareTo(o.getSortKey());
}
+
+ /** Is it worth executing this task now? */
+ public boolean isExecutable(OsgiControllerTaskContext ctx) throws
Exception {
+ return true;
+ }
@Override
public final boolean equals(Object o) {
Modified:
sling/trunk/contrib/extensions/jcrinstall/osgi/src/main/java/org/apache/sling/osgi/installer/impl/tasks/BundleStartTask.java
URL:
http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/jcrinstall/osgi/src/main/java/org/apache/sling/osgi/installer/impl/tasks/BundleStartTask.java?rev=793010&r1=793009&r2=793010&view=diff
==============================================================================
---
sling/trunk/contrib/extensions/jcrinstall/osgi/src/main/java/org/apache/sling/osgi/installer/impl/tasks/BundleStartTask.java
(original)
+++
sling/trunk/contrib/extensions/jcrinstall/osgi/src/main/java/org/apache/sling/osgi/installer/impl/tasks/BundleStartTask.java
Fri Jul 10 16:21:25 2009
@@ -20,10 +20,14 @@
import java.text.DecimalFormat;
+import org.apache.sling.osgi.installer.JcrInstallException;
+import org.apache.sling.osgi.installer.impl.EventsCounter;
import org.apache.sling.osgi.installer.impl.OsgiControllerTask;
import org.apache.sling.osgi.installer.impl.OsgiControllerTaskContext;
import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
+import org.osgi.framework.ServiceReference;
import org.osgi.service.log.LogService;
/** Task that starts a bundle */
@@ -31,6 +35,8 @@
private final long bundleId;
private final String sortKey;
+ private long eventsCountForRetrying;
+ private int retryCount = 0;
public BundleStartTask(long bundleId) {
this.bundleId = bundleId;
@@ -50,6 +56,7 @@
public void execute(OsgiControllerTaskContext tctx) throws Exception {
final Bundle b = tctx.getBundleContext().getBundle(bundleId);
final LogService log =
tctx.getOsgiControllerServices().getLogService();
+ boolean needToRetry = false;
if(b == null) {
if(log != null) {
@@ -58,24 +65,70 @@
return;
}
- if(b.getState() == Bundle.ACTIVE) {
- if(log != null) {
- log.log(LogService.LOG_DEBUG, "Bundle already
started, no action taken:" + bundleId + "/" + b.getSymbolicName());
- }
- } else {
- try {
- b.start();
- if(log != null) {
- log.log(LogService.LOG_INFO, "Bundle
started:" + bundleId + "/" + b.getSymbolicName());
- }
- } catch(BundleException e) {
- if(log != null) {
- log.log(LogService.LOG_INFO,
- "Could not start bundle
(" + e + "), will retry: " + bundleId + "/" + b.getSymbolicName());
- }
- tctx.addTaskToNextCycle(this);
- }
-
+ try {
+ if(b.getState() == Bundle.ACTIVE) {
+ if(log != null) {
+ log.log(LogService.LOG_DEBUG, "Bundle already started,
no action taken:" + bundleId + "/" + b.getSymbolicName());
+ }
+ } else {
+ // Try to start bundle, and if that doesn't work we'll need
to retry
+ try {
+ b.start();
+ if(log != null) {
+ log.log(LogService.LOG_INFO,
+ "Bundle started (retry count=" + retryCount
+ ", bundle ID=" + bundleId + ") " + b.getSymbolicName());
+ }
+ } catch(BundleException e) {
+ if(log != null) {
+ log.log(LogService.LOG_INFO,
+ "Could not start bundle (retry count=" +
retryCount + ", " + e
+ + "), will retry: " + bundleId + "/" +
b.getSymbolicName());
+ }
+ needToRetry = true;
+ }
+
+ }
+ } finally {
+ if(needToRetry) {
+
+ // Do the first retry immediately (in case "something"
happenened right now
+ // that warrants a retry), but for the next ones wait for
at least one bundle
+ // event or framework event
+ if(retryCount == 0) {
+ eventsCountForRetrying =
getEventsCount(tctx.getBundleContext());
+ } else {
+ eventsCountForRetrying =
getEventsCount(tctx.getBundleContext()) + 1;
+ }
+
+ tctx.addTaskToNextCycle(this);
+ }
}
+ retryCount++;
}
+
+ /** Do not execute this task if waiting for events */
+ public boolean isExecutable(OsgiControllerTaskContext tctx) throws
JcrInstallException {
+ final long eventsCount = getEventsCount(tctx.getBundleContext());
+ final boolean result = eventsCount >= eventsCountForRetrying;
+ if(!result) {
+ if(tctx.getOsgiControllerServices().getLogService() != null) {
+
tctx.getOsgiControllerServices().getLogService().log(LogService.LOG_DEBUG,
+ this + " is not executable at this time, counters=" +
eventsCountForRetrying + "/" + eventsCount);
+ }
+ }
+ return result;
+ }
+
+ /** Return current events count */
+ protected long getEventsCount(BundleContext bc) throws JcrInstallException
{
+ final ServiceReference sr =
bc.getServiceReference(EventsCounter.class.getName());
+ if(sr == null) {
+ throw new JcrInstallException("EventsCounter service not found");
+ }
+ final EventsCounter ec = (EventsCounter)bc.getService(sr);
+ if(ec == null) {
+ throw new JcrInstallException("EventsCounter service not found,
although its ServiceReference was found");
+ }
+ return ec.getTotalEventsCount();
+ }
}