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 2009/09/17 15:37:10 UTC

svn commit: r816185 - in /sling/trunk/installer/osgi: installer/src/main/java/org/apache/sling/osgi/installer/impl/ installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/ installer/src/test/java/org/apache/sling/osgi/installer/impl/ it/src...

Author: bdelacretaz
Date: Thu Sep 17 13:37:09 2009
New Revision: 816185

URL: http://svn.apache.org/viewvc?rev=816185&view=rev
Log:
SLING-1078 - store bundle digests to avoid unnecessary snapshot updates

Modified:
    sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/OsgiInstallerContext.java
    sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/OsgiInstallerImpl.java
    sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/BundleInstallTask.java
    sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/BundleUpdateTask.java
    sling/trunk/installer/osgi/installer/src/test/java/org/apache/sling/osgi/installer/impl/MockOsgiInstallerContext.java
    sling/trunk/installer/osgi/it/src/test/java/org/apache/sling/osgi/installer/it/BundleSnapshotUpdateTest.java
    sling/trunk/installer/osgi/it/src/test/java/org/apache/sling/osgi/installer/it/OsgiInstallerTestBase.java

Modified: sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/OsgiInstallerContext.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/OsgiInstallerContext.java?rev=816185&r1=816184&r2=816185&view=diff
==============================================================================
--- sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/OsgiInstallerContext.java (original)
+++ sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/OsgiInstallerContext.java Thu Sep 17 13:37:09 2009
@@ -18,6 +18,8 @@
  */
 package org.apache.sling.osgi.installer.impl;
 
+import java.io.IOException;
+
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Version;
@@ -43,4 +45,12 @@
 	 * 	usually to indicate that a task must be retried 
 	 */
 	void addTaskToNextCycle(OsgiInstallerTask t);
+	
+	/** Store a bundle's digest, keyed by symbolic ID + version */
+	void saveBundleDigest(Bundle b, String digest) throws IOException;
+	
+	/** Retrieve a bundle's digest that was stored by storeBundleDigest 
+	 *  @return null if no digest was stored   
+	 * */
+	String getBundleDigest(Bundle b) throws IOException;
 }

Modified: sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/OsgiInstallerImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/OsgiInstallerImpl.java?rev=816185&r1=816184&r2=816185&view=diff
==============================================================================
--- sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/OsgiInstallerImpl.java (original)
+++ sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/OsgiInstallerImpl.java Thu Sep 17 13:37:09 2009
@@ -18,13 +18,19 @@
  */
 package org.apache.sling.osgi.installer.impl;
 
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
 import java.io.IOException;
+import java.io.PrintWriter;
 import java.util.Collection;
 
 import org.apache.sling.osgi.installer.InstallableResource;
 import org.apache.sling.osgi.installer.OsgiInstaller;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceReference;
 import org.osgi.framework.Version;
 import org.osgi.service.cm.ConfigurationAdmin;
@@ -42,6 +48,8 @@
     private final ServiceTracker logServiceTracker;
     private final OsgiInstallerThread installerThread;
     private long [] counters = new long[COUNTERS_SIZE];
+    
+    public static String BUNDLE_DIGEST_PREFIX = "bundle-digest-";
 
     public OsgiInstallerImpl(final BundleContext bc,
                               final PackageAdmin pa,
@@ -56,8 +64,14 @@
         installerThread.start();
     }
 
-    public void deactivate() {
+    public void deactivate() throws InterruptedException {
         installerThread.deactivate();
+        
+        if(getLogService() != null) {
+            getLogService().log(LogService.LOG_INFO, "Waiting for installer thread to stop");
+        }
+        installerThread.join();
+        
         if(getLogService() != null) {
             getLogService().log(LogService.LOG_WARNING,
                     OsgiInstaller.class.getName()
@@ -156,4 +170,37 @@
 	public boolean isSnapshot(Version v) {
 		return v.toString().indexOf(MAVEN_SNAPSHOT_MARKER) >= 0;
 	}
+
+    public String getBundleDigest(Bundle b) throws IOException {
+        // TODO it would be cleaner to use a single file to 
+        // store those digests - and currently digests files
+        // are not purged
+        String result = null;
+        final File f = getBundleDigestFile(b);
+        if(f.exists()) {
+            final FileReader fr = new FileReader(f);
+            try {
+                result = new BufferedReader(fr).readLine();
+            } finally {
+                fr.close();
+            }
+        }
+        return result;
+    }
+
+    public void saveBundleDigest(Bundle b, String digest) throws IOException {
+        final File f = getBundleDigestFile(b);
+        final FileWriter fw = new FileWriter(f);
+        try {
+            new PrintWriter(fw).write(digest);
+        } finally {
+            fw.close();
+        }
+    }
+    
+    private File getBundleDigestFile(Bundle b) {
+        final String version = (String)b.getHeaders().get(Constants.BUNDLE_VERSION);
+        final String filename = BUNDLE_DIGEST_PREFIX + b.getSymbolicName() + version + ".txt";
+        return bundleContext.getDataFile(filename);
+    }
 }
\ No newline at end of file

Modified: sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/BundleInstallTask.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/BundleInstallTask.java?rev=816185&r1=816184&r2=816185&view=diff
==============================================================================
--- sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/BundleInstallTask.java (original)
+++ sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/BundleInstallTask.java Thu Sep 17 13:37:09 2009
@@ -41,6 +41,7 @@
     
     public void execute(OsgiInstallerContext ctx) throws Exception {
         final Bundle b = ctx.getBundleContext().installBundle(resource.getUrl(), resource.getInputStream());
+        ctx.saveBundleDigest(b, resource.getDigest());
         logExecution(ctx);
         ctx.addTaskToCurrentCycle(new BundleStartTask(b.getBundleId()));
         ctx.incrementCounter(OsgiInstaller.OSGI_TASKS_COUNTER);

Modified: sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/BundleUpdateTask.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/BundleUpdateTask.java?rev=816185&r1=816184&r2=816185&view=diff
==============================================================================
--- sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/BundleUpdateTask.java (original)
+++ sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/BundleUpdateTask.java Thu Sep 17 13:37:09 2009
@@ -57,10 +57,12 @@
         }
         
         // Do not update if same version, unless snapshot
+        boolean snapshot = false;
         if(b != null) {
         	final Version currentVersion = new Version((String)b.getHeaders().get(Constants.BUNDLE_VERSION));
         	final Version newVersion = (Version)resource.getAttributes().get(Constants.BUNDLE_VERSION);
-        	if(currentVersion.equals(newVersion) && !ctx.isSnapshot(newVersion)) {
+        	snapshot = ctx.isSnapshot(newVersion);
+        	if(currentVersion.equals(newVersion) && !snapshot) {
         		if(ctx.getLogService() != null) {
             		ctx.getLogService().log(
             				LogService.LOG_DEBUG, 
@@ -70,6 +72,21 @@
         	}
         }
         
+        // If snapshot and ready to update, cancel if digest didn't change - as the list
+        // of RegisteredResources is not saved, this might not have been detected earlier,
+        // if the snapshot was installed and the installer was later restarted
+        if( (b != null) && snapshot) {
+            final String oldDigest = ctx.getBundleDigest(b);
+            if(resource.getDigest().equals(oldDigest)) {
+                if(ctx.getLogService() != null) {
+                    ctx.getLogService().log(
+                            LogService.LOG_DEBUG, 
+                            "Snapshot digest did not change, ignoring update:" + resource);
+                }
+                return;
+            }
+        }
+        
         logExecution(ctx);
         if(b.getState() == Bundle.ACTIVE) {
             // bundle was active before the update - restart it once updated, but
@@ -78,6 +95,7 @@
         }
         b.stop();
         b.update(resource.getInputStream());
+        ctx.saveBundleDigest(b, resource.getDigest());
         if(ctx.getLogService() != null) {
             ctx.getLogService().log(LogService.LOG_DEBUG, "Bundle updated: " + b.getBundleId() + "/" + b.getSymbolicName());
         }
@@ -89,4 +107,4 @@
         return TaskOrder.BUNDLE_UPDATE_ORDER + resource.getUrl();
     }
 
-}
+}
\ No newline at end of file

Modified: sling/trunk/installer/osgi/installer/src/test/java/org/apache/sling/osgi/installer/impl/MockOsgiInstallerContext.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/installer/src/test/java/org/apache/sling/osgi/installer/impl/MockOsgiInstallerContext.java?rev=816185&r1=816184&r2=816185&view=diff
==============================================================================
--- sling/trunk/installer/osgi/installer/src/test/java/org/apache/sling/osgi/installer/impl/MockOsgiInstallerContext.java (original)
+++ sling/trunk/installer/osgi/installer/src/test/java/org/apache/sling/osgi/installer/impl/MockOsgiInstallerContext.java Thu Sep 17 13:37:09 2009
@@ -18,6 +18,8 @@
  */
 package org.apache.sling.osgi.installer.impl;
 
+import java.io.IOException;
+
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Version;
@@ -62,4 +64,11 @@
 	public boolean isSnapshot(Version v) {
 		return v.toString().indexOf(OsgiInstallerImpl.MAVEN_SNAPSHOT_MARKER) >= 0;
 	}
+
+    public String getBundleDigest(Bundle b) throws IOException {
+        return null;
+    }
+
+    public void saveBundleDigest(Bundle b, String digest) throws IOException {
+    }
 }

Modified: sling/trunk/installer/osgi/it/src/test/java/org/apache/sling/osgi/installer/it/BundleSnapshotUpdateTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/it/src/test/java/org/apache/sling/osgi/installer/it/BundleSnapshotUpdateTest.java?rev=816185&r1=816184&r2=816185&view=diff
==============================================================================
--- sling/trunk/installer/osgi/it/src/test/java/org/apache/sling/osgi/installer/it/BundleSnapshotUpdateTest.java (original)
+++ sling/trunk/installer/osgi/it/src/test/java/org/apache/sling/osgi/installer/it/BundleSnapshotUpdateTest.java Thu Sep 17 13:37:09 2009
@@ -30,6 +30,7 @@
 import org.ops4j.pax.exam.Option;
 import org.ops4j.pax.exam.junit.JUnit4TestRunner;
 import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleException;
 
 /** Verify that snapshot bundles are updated even if
  *  their version number does not change.
@@ -86,8 +87,7 @@
         assertNoOsgiTasks("At end of test");
     }
     
-    @Test
-    public void testSnapshot() throws IOException {
+    private void testSnapshotPrimitive(boolean restartInstaller) throws IOException, BundleException {
         
         // Install test bundle
         final String symbolicName = "osgi-installer-snapshot-test";
@@ -100,6 +100,10 @@
         final Bundle b = findBundle(symbolicName);
         assertNotNull("Snapshot bundle must be found after waitForInstallerAction", b);
 
+        if(restartInstaller) {
+            restartInstaller();
+        }
+        
         // Update with same digest must be ignored
         final long nOps = installer.getCounters()[OsgiInstaller.OSGI_TASKS_COUNTER];
         installer.addResource(getInstallableResource(
@@ -118,4 +122,14 @@
         // And no more OSGi tasks after that
         assertNoOsgiTasks("At end of test");
     }
-}
+
+    @Test
+    public void testSnapshot() throws IOException, BundleException {
+        testSnapshotPrimitive(false);
+    }
+    
+    @Test
+    public void testSnapshotWithInstallerRestart() throws IOException, BundleException {
+        testSnapshotPrimitive(true);
+    }
+}
\ No newline at end of file

Modified: sling/trunk/installer/osgi/it/src/test/java/org/apache/sling/osgi/installer/it/OsgiInstallerTestBase.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/it/src/test/java/org/apache/sling/osgi/installer/it/OsgiInstallerTestBase.java?rev=816185&r1=816184&r2=816185&view=diff
==============================================================================
--- sling/trunk/installer/osgi/it/src/test/java/org/apache/sling/osgi/installer/it/OsgiInstallerTestBase.java (original)
+++ sling/trunk/installer/osgi/it/src/test/java/org/apache/sling/osgi/installer/it/OsgiInstallerTestBase.java Thu Sep 17 13:37:09 2009
@@ -40,6 +40,7 @@
 import org.ops4j.pax.exam.Option;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
 import org.osgi.framework.Constants;
 import org.osgi.framework.FrameworkEvent;
 import org.osgi.framework.FrameworkListener;
@@ -94,6 +95,18 @@
         }
     }
     
+    protected void restartInstaller() throws BundleException {
+        final String symbolicName = "org.apache.sling.osgi.installer";
+        final Bundle b = findBundle(symbolicName);
+        if(b == null) {
+            fail("Bundle " + symbolicName + " not found");
+        }
+        log(LogService.LOG_INFO, "Restarting " + symbolicName + " bundle");
+        b.stop();
+        b.start();
+        setupInstaller();
+    }
+    
     protected void generateBundleEvent() throws Exception {
         // install a bundle manually to generate a bundle event
         final File f = getTestBundle("org.apache.sling.osgi.installer.it-" + POM_VERSION + "-testbundle-1.0.jar");