You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by bd...@apache.org on 2008/08/25 14:01:10 UTC
svn commit: r688702 - in
/incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles:
BundleNodeProcessor.java JcrBundlesManager.java
Author: bdelacretaz
Date: Mon Aug 25 05:01:09 2008
New Revision: 688702
URL: http://svn.apache.org/viewvc?rev=688702&view=rev
Log:
SLING-587 - take BundleEvents into account for processing the list of pending bundles
Modified:
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/BundleNodeProcessor.java
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/JcrBundlesManager.java
Modified: incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/BundleNodeProcessor.java
URL: http://svn.apache.org/viewvc/incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/BundleNodeProcessor.java?rev=688702&r1=688701&r2=688702&view=diff
==============================================================================
--- incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/BundleNodeProcessor.java (original)
+++ incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/BundleNodeProcessor.java Mon Aug 25 05:01:09 2008
@@ -74,13 +74,7 @@
changed = true;
newBundle = getBundleContext().installBundle(location, is);
if (!isFragment(newBundle)) {
- if ((newBundle.getState() & Bundle.RESOLVED) > 0) {
- newBundle.start();
- log.info("Bundle {} successfully installed and started", location);
- } else {
- mgr.addPendingBundle(location, newBundle);
- log.info("Bundle {} not resolved. delay start", location);
- }
+ mgr.addPendingBundle(location, newBundle);
} else {
log.info("Fragment bundle {} successfully installed", location);
}
@@ -104,8 +98,8 @@
log.info("Bundle {} successfully updated", location);
status.setProperty("status", "updated");
} catch (BundleException e) {
- log.info("Bundle {} could not be updated. adding to pending list", location, e);
mgr.addPendingBundle(location, oldBundle);
+ log.info("Bundle {} could not be updated. added to list of pending bundles", location, e);
}
} else {
log.debug("Bundle {} unchanged, no update needed", location);
Modified: incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/JcrBundlesManager.java
URL: http://svn.apache.org/viewvc/incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/JcrBundlesManager.java?rev=688702&r1=688701&r2=688702&view=diff
==============================================================================
--- incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/JcrBundlesManager.java (original)
+++ incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/JcrBundlesManager.java Mon Aug 25 05:01:09 2008
@@ -18,13 +18,16 @@
*/
package org.apache.sling.jcr.jcrbundles;
+import static org.apache.sling.jcr.jcrbundles.JcrBundlesConstants.BUNDLES_NODENAME;
+import static org.apache.sling.jcr.jcrbundles.JcrBundlesConstants.STATUS_BASE_PATH;
+
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.Iterator;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
@@ -32,12 +35,13 @@
import javax.jcr.observation.Event;
import org.apache.sling.jcr.api.SlingRepository;
-import static org.apache.sling.jcr.jcrbundles.JcrBundlesConstants.BUNDLES_NODENAME;
-import static org.apache.sling.jcr.jcrbundles.JcrBundlesConstants.STATUS_BASE_PATH;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.SynchronousBundleListener;
import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.packageadmin.PackageAdmin;
-import org.osgi.framework.Bundle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -54,7 +58,7 @@
* value="The Apache Software Foundation"
*/
-public class JcrBundlesManager implements Runnable {
+public class JcrBundlesManager implements Runnable, SynchronousBundleListener {
/**
* Ordered list of root paths to observe for bundles and configs
* TODO should be configurable
@@ -94,6 +98,8 @@
private Session session;
protected final Logger log = LoggerFactory.getLogger(this.getClass());
private boolean running;
+ private boolean processPendingBundles;
+ private long loopDelay;
private final Map<String, Bundle> pendingBundles = new HashMap<String, Bundle>();
@@ -103,6 +109,10 @@
*/
protected void activate(ComponentContext context) throws RepositoryException {
+ // Listen to bundle events to find out if our pending bundles list
+ // needs processing
+ context.getBundleContext().addBundleListener(this);
+
// setup our processors
processors = new LinkedList<NodeProcessor>();
processors.add(new BundleNodeProcessor(this, context, padmin));
@@ -153,6 +163,8 @@
protected void deactivate(ComponentContext oldContext) {
running = false;
+ oldContext.getBundleContext().removeBundleListener(this);
+
for (BundlesFolder bf : folders) {
try {
bf.cleanup();
@@ -181,18 +193,25 @@
protected void addPendingBundle(String path, Bundle bundle) {
synchronized (pendingBundles) {
+ processPendingBundles = true;
pendingBundles.put(path, bundle);
+ log.debug("Bundle {} added to list of pending bundles.", path);
}
}
protected void removePendingBundle(String path) {
synchronized (pendingBundles) {
+ processPendingBundles = true;
if (pendingBundles.remove(path) != null) {
- log.info("Removed bundle {} from pending list.", path);
+ log.debug("Removed bundle {} from pending list.", path);
}
}
}
+ public void bundleChanged(BundleEvent event) {
+ processPendingBundles = true;
+ }
+
/**
* Scan paths once their timer expires
*/
@@ -206,7 +225,7 @@
statusFolder = new BundlesFolder(repository, STATUS_BASE_PATH, processors);
final Map<String, Boolean> flags = new HashMap<String, Boolean>();
statusFolder.checkDeletions(flags);
- refreshPackagesIfNeeded(flags);
+ refreshAndResolve(flags);
} catch (Exception e) {
log.error("Exception during initial scanning of " + STATUS_BASE_PATH, e);
} finally {
@@ -221,6 +240,7 @@
// We could use the scheduler service but that makes things harder to test
while (running) {
+ loopDelay = 1000L;
try {
s = repository.loginAdministrative(repository.getDefaultWorkspace());
runOneCycle(s);
@@ -237,7 +257,7 @@
s = null;
}
try {
- Thread.sleep(1000L);
+ Thread.sleep(loopDelay);
} catch (InterruptedException ignore) {
// ignore
}
@@ -260,9 +280,9 @@
}
}
- // Let ouf BundlesFolders do their work
final Map<String, Boolean> flags = new HashMap<String, Boolean>();
-
+
+ // Let our BundlesFolders do their work
for (BundlesFolder bf : folders) {
if (!running) {
break;
@@ -270,54 +290,86 @@
bf.scanIfNeeded(flags);
}
- // try to resolve pending bundles
+ // Process bundles that could not be started or resolved, if any
+ processPendingBundles(flags);
+
+ // Refresh/resolve packages if needed
+ refreshAndResolve(flags);
+ }
+
+ /** Process pending bundles if needed */
+ private void processPendingBundles(Map<String, Boolean> flags) throws BundleException {
synchronized (pendingBundles) {
- boolean tryStart = true;
- while (tryStart) {
- tryStart = false;
- Iterator<String> iter = pendingBundles.keySet().iterator();
- while (iter.hasNext()) {
- String location = iter.next();
- Bundle bundle = pendingBundles.get(location);
- log.info("Checking bundle {} which status is " + bundle.getState(), location);
- if ((bundle.getState() & Bundle.ACTIVE) > 0) {
- log.info("Bundle {} is active.", location);
- flags.put("refresh.packages", Boolean.TRUE);
- flags.put("resolve.bundles", Boolean.TRUE);
- iter.remove();
- } else if ((bundle.getState() & Bundle.STARTING) > 0) {
- log.info("Bundle {} is starting.", location);
- } else if ((bundle.getState() & Bundle.STOPPING) > 0) {
- log.info("Bundle {} is stopping.", location);
- } else if ((bundle.getState() & Bundle.UNINSTALLED) > 0) {
- log.info("Bundle {} is uninstalled.", location);
- iter.remove();
- } else if ((bundle.getState() & Bundle.RESOLVED) > 0) {
- log.info("Bundle {} is resolved, starting it.", location);
- flags.put("resolve.bundles", Boolean.TRUE);
- bundle.start();
- tryStart = true;
- } else if ((bundle.getState() & Bundle.INSTALLED) > 0) {
- log.info("Bundle {} is installed but not resolved.", location);
- flags.put("resolve.bundles", Boolean.TRUE);
- }
+
+ // Do nothing if list is empty or if no interesting events happened
+ // since last processed
+ if(!processPendingBundles || pendingBundles.isEmpty()) {
+ return;
+ }
+ processPendingBundles = false;
+
+ log.debug("Processing {} pending bundles", pendingBundles.size());
+
+ // If we start or resolve any bundles, trigger the next
+ // scanning loop immediately, as that might allow more
+ // bundles to start
+ boolean scanImmediately = false;
+
+ // Walk the list of pending bundles
+ final Iterator<String> iter = pendingBundles.keySet().iterator();
+ while (iter.hasNext()) {
+ String location = iter.next();
+ Bundle bundle = pendingBundles.get(location);
+ log.debug("Checking bundle {}, current state={}", location, bundle.getState());
+
+ if ((bundle.getState() & Bundle.ACTIVE) > 0) {
+ log.info("Bundle {} is active.", location);
+ flags.put("refresh.packages", Boolean.TRUE);
+ flags.put("resolve.bundles", Boolean.TRUE);
+ scanImmediately = true;
+ processPendingBundles = true;
+ iter.remove();
+
+ } else if ((bundle.getState() & Bundle.STARTING) > 0) {
+ log.info("Bundle {} is starting.", location);
+
+ } else if ((bundle.getState() & Bundle.STOPPING) > 0) {
+ log.info("Bundle {} is stopping.", location);
+
+ } else if ((bundle.getState() & Bundle.UNINSTALLED) > 0) {
+ log.info("Bundle {} is uninstalled.", location);
+ processPendingBundles = true;
+ iter.remove();
+
+ } else if ((bundle.getState() & Bundle.RESOLVED) > 0) {
+ log.info("Bundle {} is resolved, trying to start it.", location);
+ flags.put("resolve.bundles", Boolean.TRUE);
+ bundle.start();
+ scanImmediately = true;
+
+ } else if ((bundle.getState() & Bundle.INSTALLED) > 0) {
+ log.info("Bundle {} is installed but not resolved.", location);
+ flags.put("resolve.bundles", Boolean.TRUE);
+ scanImmediately = true;
}
}
- if (!pendingBundles.isEmpty()) {
- log.info("Could not start all pending bundles. Still {} remaining.", pendingBundles.size());
+
+ log.debug("Done processing pending bundles, {} bundles left in list", pendingBundles.size());
+
+ if(scanImmediately) {
+ loopDelay = 0;
}
}
-
- refreshPackagesIfNeeded(flags);
}
- void refreshPackagesIfNeeded(Map<String, Boolean> flags) {
+ /** If flags say so, refresh/resolve packages */
+ void refreshAndResolve(Map<String, Boolean> flags) {
if (Boolean.TRUE.equals(flags.get("resolve.bundles"))) {
- log.info("Resolving bundles");
+ log.debug("Resolving bundles");
padmin.resolveBundles(null);
}
if (Boolean.TRUE.equals(flags.get("refresh.packages"))) {
- log.info("Refreshing packages");
+ log.debug("Refreshing packages");
padmin.refreshPackages(null);
}
}