Author: bdelacretaz Date: Fri Nov 14 05:45:12 2008 New Revision: 714001 URL: http://svn.apache.org/viewvc?rev=714001&view=rev Log: SLING-733 - Process resource detection and installation in sequence instead of asynchronously
Modified: incubator/sling/trunk/extensions/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/jcr/impl/RepositoryObserver.java incubator/sling/trunk/extensions/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/jcr/impl/WatchedFolder.java incubator/sling/trunk/extensions/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/osgi/OsgiController.java incubator/sling/trunk/extensions/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/osgi/impl/OsgiControllerImpl.java incubator/sling/trunk/extensions/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/ResourceDetectionTest.java incubator/sling/trunk/extensions/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/osgi/impl/BundleResourceProcessorTest.java Modified: incubator/sling/trunk/extensions/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/jcr/impl/RepositoryObserver.java URL: http://svn.apache.org/viewvc/incubator/sling/trunk/extensions/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/jcr/impl/RepositoryObserver.java?rev=714001&r1=714000&r2=714001&view=diff ============================================================================== --- incubator/sling/trunk/extensions/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/jcr/impl/RepositoryObserver.java (original) +++ incubator/sling/trunk/extensions/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/jcr/impl/RepositoryObserver.java Fri Nov 14 05:45:12 2008 @@ -284,7 +284,7 @@ final Node parent = n.getParent(); if(!folderNameFilter.accept(parent.getPath())) { log.info("Uninstalling resource {}, folder name not accepted by current filter", uri); - osgiController.uninstall(uri); + osgiController.scheduleUninstall(uri); } } } @@ -359,11 +359,16 @@ /** Let our WatchedFolders run their scanning cycles */ void runOneCycle() throws Exception { - boolean forceScan = false; + + // Add any new watched folders, and scan those who need it addNewWatchedFolders(); for(WatchedFolder wf : folders) { wf.scanIfNeeded(converters); } + + // And then let the OsgiController install/remove + // resources that we detected + osgiController.executeScheduledOperations(); } Properties loadProperties(File f) { Modified: incubator/sling/trunk/extensions/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/jcr/impl/WatchedFolder.java URL: http://svn.apache.org/viewvc/incubator/sling/trunk/extensions/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/jcr/impl/WatchedFolder.java?rev=714001&r1=714000&r2=714001&view=diff ============================================================================== --- incubator/sling/trunk/extensions/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/jcr/impl/WatchedFolder.java (original) +++ incubator/sling/trunk/extensions/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/jcr/impl/WatchedFolder.java Fri Nov 14 05:45:12 2008 @@ -195,7 +195,7 @@ log.info("Resource {} has been deleted, uninstalling", uri); // a single failure must not block the whole thing (SLING-655) try { - controller.uninstall(uri); + controller.scheduleUninstall(uri); } catch(JcrInstallException jie) { log.warn("Failed to uninstall " + uri, jie); } @@ -229,10 +229,10 @@ final String digest = controller.getDigest(path); if(digest == null) { log.info("Resource {} was not installed yet, installing in OsgiController", path); - controller.installOrUpdate(path, fdp); + controller.scheduleInstallOrUpdate(path, fdp); } else if(!digest.equals(fdp.getDigest())) { log.info("Resource {} has been updated, updating in OsgiController", path); - controller.installOrUpdate(path, fdp); + controller.scheduleInstallOrUpdate(path, fdp); } else { log.info("Resource {} not modified, ignoring", path); } Modified: incubator/sling/trunk/extensions/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/osgi/OsgiController.java URL: http://svn.apache.org/viewvc/incubator/sling/trunk/extensions/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/osgi/OsgiController.java?rev=714001&r1=714000&r2=714001&view=diff ============================================================================== --- incubator/sling/trunk/extensions/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/osgi/OsgiController.java (original) +++ incubator/sling/trunk/extensions/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/osgi/OsgiController.java Fri Nov 14 05:45:12 2008 @@ -27,19 +27,19 @@ */ public interface OsgiController { - /** Install or update supplied resource + /** Schedule installation or update of supplied resource * @param uri Unique identifier for the resource * @param data The data to install * @return one of the [EMAIL PROTECTED] InstallResultCode} result codes. */ - int installOrUpdate(String uri, InstallableData data) throws IOException, JcrInstallException; + int scheduleInstallOrUpdate(String uri, InstallableData data) throws IOException, JcrInstallException; - /** Uninstall the data that was installed via given uri + /** Schedule uninstallation of resource that was installed via given uri * @param uri Unique identifier for the resource * @param attributes metadata stored by the OsgiController, will be * removed after calling this method */ - void uninstall(String uri) throws JcrInstallException; + void scheduleUninstall(String uri) throws JcrInstallException; /** Return the list of uri for resources that have been installed * by this controller. @@ -54,4 +54,7 @@ /** Optionally set ResourceOverrideRules */ void setResourceOverrideRules(ResourceOverrideRules r); + + /** Do the actual installs/uninistalls which were scheduled by the other methods */ + void executeScheduledOperations() throws Exception; } Modified: incubator/sling/trunk/extensions/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/osgi/impl/OsgiControllerImpl.java URL: http://svn.apache.org/viewvc/incubator/sling/trunk/extensions/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/osgi/impl/OsgiControllerImpl.java?rev=714001&r1=714000&r2=714001&view=diff ============================================================================== --- incubator/sling/trunk/extensions/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/osgi/impl/OsgiControllerImpl.java (original) +++ incubator/sling/trunk/extensions/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/osgi/impl/OsgiControllerImpl.java Fri Nov 14 05:45:12 2008 @@ -52,13 +52,11 @@ * name="service.vendor" * value="The Apache Software Foundation" */ -public class OsgiControllerImpl implements OsgiController, Runnable, SynchronousBundleListener { +public class OsgiControllerImpl implements OsgiController, SynchronousBundleListener { private Storage storage; private List<OsgiResourceProcessor> processors; private final Logger log = LoggerFactory.getLogger(this.getClass()); - private boolean running; - private long loopDelay; private ResourceOverrideRules roRules; public static final String STORAGE_FILENAME = "controller.storage"; @@ -76,22 +74,17 @@ public static final long LAST_MODIFIED_NOT_FOUND = -1; protected void activate(ComponentContext context) throws IOException { + + // Note that, in executeScheduledOperations(), + // processors are called in the order of this list processors = new LinkedList<OsgiResourceProcessor>(); processors.add(new BundleResourceProcessor(context.getBundleContext(), packageAdmin)); processors.add(new ConfigResourceProcessor(configAdmin)); storage = new Storage(context.getBundleContext().getDataFile(STORAGE_FILENAME)); - - // start queue processing - running = true; - final Thread t = new Thread(this, getClass().getSimpleName() + "_" + System.currentTimeMillis()); - t.setDaemon(true); - t.start(); } protected void deactivate(ComponentContext oldContext) { - running = false; - if(storage != null) { try { storage.saveToFile(); @@ -110,7 +103,7 @@ processors = null; } - public int installOrUpdate(String uri, InstallableData data) throws IOException, JcrInstallException { + public int scheduleInstallOrUpdate(String uri, InstallableData data) throws IOException, JcrInstallException { int result = IGNORED; // If a corresponding higher priority resource is already installed, ignore this one @@ -130,7 +123,7 @@ if(storage.contains(r)) { log.info("Resource {} overrides {}, uninstalling the latter", uri, r); - uninstall(uri); + scheduleUninstall(uri); } } } @@ -154,7 +147,7 @@ return result; } - public void uninstall(String uri) throws JcrInstallException { + public void scheduleUninstall(String uri) throws JcrInstallException { // If a corresponding higher priority resource is installed, ignore this request if(roRules != null) { for(String r : roRules.getHigherPriorityResources(uri)) { @@ -229,34 +222,14 @@ //loopDelay = 0; } - /** Process our resource queues at regular intervals, more often if - * we received bundle events since the last processing - */ - public void run() { - log.info("{} thread {} starts", getClass().getSimpleName(), Thread.currentThread().getName()); - - // We could use the scheduler service but that makes things harder to test - while (running) { - loopDelay = 1000; - try { - for(OsgiResourceProcessor p : processors) { - p.processResourceQueue(); - } - } catch (Exception e) { - log.warn("Exception in run()", e); - } finally { - try { - Thread.sleep(loopDelay); - } catch (InterruptedException ignore) { - // ignore - } - } + /** [EMAIL PROTECTED] */ + public void executeScheduledOperations() throws Exception { + for(OsgiResourceProcessor p : processors) { + p.processResourceQueue(); } + } - log.info("{} thread {} ends", getClass().getSimpleName(), Thread.currentThread().getName()); - } - - public void setResourceOverrideRules(ResourceOverrideRules r) { + public void setResourceOverrideRules(ResourceOverrideRules r) { roRules = r; } } \ No newline at end of file Modified: incubator/sling/trunk/extensions/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/ResourceDetectionTest.java URL: http://svn.apache.org/viewvc/incubator/sling/trunk/extensions/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/ResourceDetectionTest.java?rev=714001&r1=714000&r2=714001&view=diff ============================================================================== --- incubator/sling/trunk/extensions/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/ResourceDetectionTest.java (original) +++ incubator/sling/trunk/extensions/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/ResourceDetectionTest.java Fri Nov 14 05:45:12 2008 @@ -104,6 +104,7 @@ // Define the whole sequence of calls to OsgiController, // Using getLastModified calls to mark the test phases mockery.checking(new Expectations() {{ + allowing(c).executeScheduledOperations(); allowing(c).setResourceOverrideRules(with(any(ResourceOverrideRules.class))); allowing(c).getInstalledUris(); will(returnValue(installedUri)); @@ -111,7 +112,7 @@ inSequence(sequence); one(c).getDigest(dummyJar); will(returnValue(null)); inSequence(sequence); - one(c).installOrUpdate(with(equal(dummyJar)), with(any(InstallableData.class))); + one(c).scheduleInstallOrUpdate(with(equal(dummyJar)), with(any(InstallableData.class))); inSequence(sequence); one(c).getDigest("phase2"); @@ -123,7 +124,7 @@ inSequence(sequence); one(c).getDigest(dummyJar); will(returnValue(da.getDigest())); inSequence(sequence); - one(c).installOrUpdate(with(equal(dummyJar)), with(any(InstallableData.class))); + one(c).scheduleInstallOrUpdate(with(equal(dummyJar)), with(any(InstallableData.class))); inSequence(sequence); }}); @@ -167,12 +168,13 @@ // Define the whole sequence of calls to OsgiController, mockery.checking(new Expectations() {{ + allowing(c).executeScheduledOperations(); allowing(c).setResourceOverrideRules(with(any(ResourceOverrideRules.class))); allowing(c).getInstalledUris(); will(returnValue(installedUri)); allowing(c).getDigest(with(any(String.class))); will(returnValue(null)); - one(c).installOrUpdate(with(equal(resources[0])), with(any(InstallableData.class))); - one(c).installOrUpdate(with(equal(resources[1])), with(any(InstallableData.class))); - one(c).installOrUpdate(with(equal(resources[2])), with(any(InstallableData.class))); + one(c).scheduleInstallOrUpdate(with(equal(resources[0])), with(any(InstallableData.class))); + one(c).scheduleInstallOrUpdate(with(equal(resources[1])), with(any(InstallableData.class))); + one(c).scheduleInstallOrUpdate(with(equal(resources[2])), with(any(InstallableData.class))); }}); final RepositoryObserver ro = new MockRepositoryObserver(repo, c); @@ -209,12 +211,13 @@ final OsgiController c = mockery.mock(OsgiController.class); mockery.checking(new Expectations() {{ + allowing(c).executeScheduledOperations(); allowing(c).setResourceOverrideRules(with(any(ResourceOverrideRules.class))); allowing(c).getInstalledUris(); will(returnValue(installedUri)); allowing(c).getDigest(with(any(String.class))); will(returnValue(null)); - one(c).installOrUpdate(with(equal(resources[0])), with(any(InstallableData.class))); - one(c).installOrUpdate(with(equal(resources[1])), with(any(InstallableData.class))); - one(c).installOrUpdate(with(equal(resources[2])), with(any(InstallableData.class))); + one(c).scheduleInstallOrUpdate(with(equal(resources[0])), with(any(InstallableData.class))); + one(c).scheduleInstallOrUpdate(with(equal(resources[1])), with(any(InstallableData.class))); + one(c).scheduleInstallOrUpdate(with(equal(resources[2])), with(any(InstallableData.class))); }}); final RepositoryObserver ro = new MockRepositoryObserver(repo, c); @@ -244,12 +247,13 @@ final RepositoryObserver ro = new MockRepositoryObserver(repo, c); mockery.checking(new Expectations() {{ + allowing(c).executeScheduledOperations(); allowing(c).setResourceOverrideRules(with(any(ResourceOverrideRules.class))); allowing(c).getInstalledUris(); will(returnValue(installedUri)); allowing(c).getDigest(with(any(String.class))); will(returnValue(null)); - one(c).uninstall("/libs/foo/bar/install/dummy.jar"); - one(c).uninstall("/libs/foo/bar/install/dummy.cfg"); - one(c).uninstall("/libs/watchfolder-is-gone/install/gone.cfg"); + one(c).scheduleUninstall("/libs/foo/bar/install/dummy.jar"); + one(c).scheduleUninstall("/libs/foo/bar/install/dummy.cfg"); + one(c).scheduleUninstall("/libs/watchfolder-is-gone/install/gone.cfg"); }}); ro.activate(null); @@ -269,15 +273,16 @@ final RepositoryObserver ro = new MockRepositoryObserver(repo, c); mockery.checking(new Expectations() {{ + allowing(c).executeScheduledOperations(); allowing(c).setResourceOverrideRules(with(any(ResourceOverrideRules.class))); allowing(c).getInstalledUris(); will(returnValue(installedUri)); allowing(c).getDigest(with(any(String.class))); will(returnValue(null)); - one(c).uninstall("/libs/foo/bar/install/dummy.cfg"); + one(c).scheduleUninstall("/libs/foo/bar/install/dummy.cfg"); inSequence(sequence); - one(c).uninstall("/libs/foo/bar/install/dummy.dp"); + one(c).scheduleUninstall("/libs/foo/bar/install/dummy.dp"); inSequence(sequence); will(throwException(new JcrInstallException("Fake BundleException for testing"))); - one(c).uninstall("/libs/foo/bar/install/dummy.jar"); + one(c).scheduleUninstall("/libs/foo/bar/install/dummy.jar"); inSequence(sequence); }}); @@ -303,13 +308,14 @@ // Define the whole sequence of calls to OsgiController, mockery.checking(new Expectations() {{ + allowing(c).executeScheduledOperations(); allowing(c).setResourceOverrideRules(with(any(ResourceOverrideRules.class))); allowing(c).getInstalledUris(); will(returnValue(installedUri)); allowing(c).getDigest(with(any(String.class))); will(returnValue(null)); - one(c).installOrUpdate(with(equal(resources[0])), with(any(InstallableData.class))); - one(c).installOrUpdate(with(equal(resources[1])), with(any(InstallableData.class))); + one(c).scheduleInstallOrUpdate(with(equal(resources[0])), with(any(InstallableData.class))); + one(c).scheduleInstallOrUpdate(with(equal(resources[1])), with(any(InstallableData.class))); will(throwException(new JcrInstallException("Fake BundleException for testing"))); - one(c).installOrUpdate(with(equal(resources[2])), with(any(InstallableData.class))); + one(c).scheduleInstallOrUpdate(with(equal(resources[2])), with(any(InstallableData.class))); }}); final RepositoryObserver ro = new MockRepositoryObserver(repo, c); @@ -350,11 +356,12 @@ // Test with first regexp mockery.checking(new Expectations() {{ + allowing(c).executeScheduledOperations(); allowing(c).setResourceOverrideRules(with(any(ResourceOverrideRules.class))); allowing(c).getInstalledUris(); will(returnValue(installedUri)); allowing(c).getDigest(with(any(String.class))); will(returnValue(null)); - one(c).installOrUpdate(with(equal(resources[0])), with(any(InstallableData.class))); - one(c).installOrUpdate(with(equal(resources[2])), with(any(InstallableData.class))); + one(c).scheduleInstallOrUpdate(with(equal(resources[0])), with(any(InstallableData.class))); + one(c).scheduleInstallOrUpdate(with(equal(resources[2])), with(any(InstallableData.class))); }}); final MockRepositoryObserver ro = new MockRepositoryObserver(repo, c, serviceDataFile); @@ -373,13 +380,14 @@ // Test with a different regexp, install.A resources must be uninstalled mockery.checking(new Expectations() {{ + allowing(c).executeScheduledOperations(); allowing(c).setResourceOverrideRules(with(any(ResourceOverrideRules.class))); allowing(c).getInstalledUris(); will(returnValue(installedUri)); allowing(c).getDigest(with(any(String.class))); will(returnValue(null)); - one(c).uninstall(resources[0]); - one(c).uninstall(resources[2]); - one(c).installOrUpdate(with(equal(resources[1])), with(any(InstallableData.class))); - one(c).installOrUpdate(with(equal(resources[3])), with(any(InstallableData.class))); + one(c).scheduleUninstall(resources[0]); + one(c).scheduleUninstall(resources[2]); + one(c).scheduleInstallOrUpdate(with(equal(resources[1])), with(any(InstallableData.class))); + one(c).scheduleInstallOrUpdate(with(equal(resources[3])), with(any(InstallableData.class))); }}); props.setProperty(RepositoryObserver.FOLDER_NAME_REGEXP_PROPERTY, ".*foo/wii/install$"); Modified: incubator/sling/trunk/extensions/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/osgi/impl/BundleResourceProcessorTest.java URL: http://svn.apache.org/viewvc/incubator/sling/trunk/extensions/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/osgi/impl/BundleResourceProcessorTest.java?rev=714001&r1=714000&r2=714001&view=diff ============================================================================== --- incubator/sling/trunk/extensions/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/osgi/impl/BundleResourceProcessorTest.java (original) +++ incubator/sling/trunk/extensions/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/osgi/impl/BundleResourceProcessorTest.java Fri Nov 14 05:45:12 2008 @@ -108,25 +108,25 @@ Utilities.setProcessors(c, p); assertFalse("Before install, uri must not be in list", c.getInstalledUris().contains(uri)); - assertEquals("First install returns INSTALLED", INSTALLED, c.installOrUpdate(uri, data)); + assertEquals("First install returns INSTALLED", INSTALLED, c.scheduleInstallOrUpdate(uri, data)); assertTrue("After install, uri must be in list", c.getInstalledUris().contains(uri)); assertEquals("Digest must have been stored", data.getDigest(), c.getDigest(uri)); assertEquals("Storage data has been saved during install", 1, s.saveCounter); data.setDigest("digest is now different"); - assertEquals("Second install returns UPDATED", UPDATED, c.installOrUpdate(uri, data)); + assertEquals("Second install returns UPDATED", UPDATED, c.scheduleInstallOrUpdate(uri, data)); assertTrue("After update, uri must be in list", c.getInstalledUris().contains(uri)); assertEquals("Digest must have been updated", data.getDigest(), c.getDigest(uri)); assertEquals("Storage data has been saved during update", 2, s.saveCounter); - c.uninstall(uri); + c.scheduleUninstall(uri); assertFalse("After uninstall, uri must not be in list", c.getInstalledUris().contains(uri)); assertEquals("Digest must be gone", null, c.getDigest(uri)); assertFalse("After getLastModified, uri must not be in list", c.getInstalledUris().contains(uri)); assertEquals("Storage data has been saved during uninstall", 3, s.saveCounter); final String nonJarUri = "no_jar_extension"; - assertEquals(nonJarUri + " must be ignored", c.installOrUpdate("", data), IGNORED); + assertEquals(nonJarUri + " must be ignored", c.scheduleInstallOrUpdate("", data), IGNORED); // And verify expectations mockery.assertIsSatisfied();