You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by ch...@apache.org on 2015/08/17 06:07:06 UTC

svn commit: r1696190 - in /jackrabbit/oak/trunk/oak-pojosr/src: main/java/org/apache/jackrabbit/oak/run/osgi/OakOSGiRepositoryFactory.java test/groovy/org/apache/jackrabbit/oak/run/osgi/AbstractRepositoryFactoryTest.groovy

Author: chetanm
Date: Mon Aug 17 04:07:06 2015
New Revision: 1696190

URL: http://svn.apache.org/r1696190
Log:
OAK-3203 - Make shutdown in PojoSR wait for framework shutdown

Modified:
    jackrabbit/oak/trunk/oak-pojosr/src/main/java/org/apache/jackrabbit/oak/run/osgi/OakOSGiRepositoryFactory.java
    jackrabbit/oak/trunk/oak-pojosr/src/test/groovy/org/apache/jackrabbit/oak/run/osgi/AbstractRepositoryFactoryTest.groovy

Modified: jackrabbit/oak/trunk/oak-pojosr/src/main/java/org/apache/jackrabbit/oak/run/osgi/OakOSGiRepositoryFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-pojosr/src/main/java/org/apache/jackrabbit/oak/run/osgi/OakOSGiRepositoryFactory.java?rev=1696190&r1=1696189&r2=1696190&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-pojosr/src/main/java/org/apache/jackrabbit/oak/run/osgi/OakOSGiRepositoryFactory.java (original)
+++ jackrabbit/oak/trunk/oak-pojosr/src/main/java/org/apache/jackrabbit/oak/run/osgi/OakOSGiRepositoryFactory.java Mon Aug 17 04:07:06 2015
@@ -29,6 +29,7 @@ import java.util.Hashtable;
 import java.util.List;
 import java.util.Map;
 import java.util.ServiceLoader;
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
@@ -50,11 +51,14 @@ import org.apache.felix.connect.launch.P
 import org.apache.felix.connect.launch.PojoServiceRegistryFactory;
 import org.apache.jackrabbit.api.JackrabbitRepository;
 import org.apache.jackrabbit.oak.commons.PropertiesUtil;
+import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
 import org.osgi.framework.BundleException;
 import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceReference;
+import org.osgi.framework.SynchronousBundleListener;
 import org.osgi.util.tracker.ServiceTracker;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -84,8 +88,8 @@ import static com.google.common.base.Pre
  *      <dt>org.apache.jackrabbit.oak.repository.bundleFilter</dt>
  *      <dd>Used to specify the bundle filter string which is passed to ClasspathScanner</dd>
  *
- *      <dt>org.apache.jackrabbit.oak.repository.startupTimeout</dt>
- *      <dd>Timeout in seconds for the repository startup should wait. Defaults to 10 minutes</dd>
+ *      <dt>org.apache.jackrabbit.oak.repository.timeoutInSecs</dt>
+ *      <dd>Timeout in seconds for the repository startup/shutdown should wait. Defaults to 10 minutes</dd>
  *
  *      <dt>org.apache.jackrabbit.oak.repository.shutDownOnTimeout</dt>
  *      <dd>Boolean flag to determine if the OSGi container should be shutdown upon timeout. Defaults to false</dd>
@@ -104,8 +108,8 @@ public class OakOSGiRepositoryFactory im
     /**
      * Timeout in seconds for the repository startup should wait
      */
-    public static final String REPOSITORY_STARTUP_TIMEOUT
-            = "org.apache.jackrabbit.oak.repository.startupTimeout";
+    public static final String REPOSITORY_TIMEOUT_IN_SECS
+            = "org.apache.jackrabbit.oak.repository.timeoutInSecs";
 
     /**
      * Config key which refers to the map of config where key in that map refers to OSGi
@@ -166,16 +170,17 @@ public class OakOSGiRepositoryFactory im
 
         new RunnableJobTracker(registry.getBundleContext());
 
+        int timeoutInSecs = PropertiesUtil.toInteger(config.get(REPOSITORY_TIMEOUT_IN_SECS), DEFAULT_TIMEOUT);
+
         //Start the tracker for repository creation
-        new RepositoryTracker(registry, activator, repoFuture);
+        new RepositoryTracker(registry, activator, repoFuture, timeoutInSecs);
 
 
         //Now wait for repository to be created with given timeout
         //if repository creation takes more time. This is required to handle case
         // where OSGi runtime fails to start due to bugs (like cycles)
-        int timeout = getTimeoutInSeconds(config);
         try {
-            return repoFuture.get(timeout, TimeUnit.SECONDS);
+            return repoFuture.get(timeoutInSecs, TimeUnit.SECONDS);
         } catch (InterruptedException e) {
             Thread.currentThread().interrupt();
             throw new RepositoryException("Repository initialization was interrupted");
@@ -184,8 +189,8 @@ public class OakOSGiRepositoryFactory im
         } catch (TimeoutException e) {
             try {
                 if (PropertiesUtil.toBoolean(config.get(REPOSITORY_SHUTDOWN_ON_TIMEOUT), true)) {
-                    shutdown(registry);
-                    log.info("OSGi container shutdown after waiting for repository initialization for {} sec",timeout);
+                    shutdown(registry, timeoutInSecs);
+                    log.info("OSGi container shutdown after waiting for repository initialization for {} sec",timeoutInSecs);
                 }else {
                     log.warn("[{}] found to be false. Container is not stopped", REPOSITORY_SHUTDOWN_ON_TIMEOUT);
                 }
@@ -194,7 +199,7 @@ public class OakOSGiRepositoryFactory im
                         "startup timeout) backing the Repository ", be);
             }
             throw new RepositoryException("Repository could not be started in " +
-                    timeout + " seconds", e);
+                    timeoutInSecs + " seconds", e);
         }
     }
 
@@ -237,9 +242,32 @@ public class OakOSGiRepositoryFactory im
         return descriptors;
     }
 
-    static void shutdown(PojoServiceRegistry registry) throws BundleException {
-        if (registry != null) {
-            registry.getBundleContext().getBundle().stop();
+    private static void shutdown(PojoServiceRegistry registry, int timeoutInSecs) throws BundleException {
+        if (registry == null){
+            return;
+        }
+        final Bundle systemBundle = registry.getBundleContext().getBundle();
+        final CountDownLatch shutdownLatch = new CountDownLatch(1);
+
+        //Logic here is similar to org.apache.felix.connect.PojoServiceRegistryFactoryImpl.FrameworkImpl.waitForStop()
+        systemBundle.getBundleContext().addBundleListener(new SynchronousBundleListener() {
+            public void bundleChanged(BundleEvent event) {
+                if (event.getBundle() == systemBundle && event.getType() == BundleEvent.STOPPED) {
+                    shutdownLatch.countDown();
+                }
+            }
+        });
+
+        //Initiate shutdown
+        systemBundle.stop();
+
+        //Wait for framework shutdown to complete
+        try {
+            shutdownLatch.await(timeoutInSecs, TimeUnit.SECONDS);
+        } catch (InterruptedException e) {
+            Thread.currentThread().interrupt();
+            throw new BundleException("Timed out while waiting for repository " +
+                    "shutdown for "+ timeoutInSecs + " secs", e);
         }
     }
 
@@ -247,14 +275,6 @@ public class OakOSGiRepositoryFactory im
         new ConfigTracker(config, registry.getBundleContext());
     }
 
-    private static int getTimeoutInSeconds(Map config) {
-        Integer timeout = (Integer) config.get(REPOSITORY_STARTUP_TIMEOUT);
-        if (timeout == null) {
-            timeout = DEFAULT_TIMEOUT;
-        }
-        return timeout;
-    }
-
     /**
      * Return the BundleActivator provided by the embedding application
      * @param config config passed to factory for initialization
@@ -350,12 +370,15 @@ public class OakOSGiRepositoryFactory im
         private final PojoServiceRegistry registry;
         private final BundleActivator activator;
         private RepositoryProxy proxy;
+        private final int timeoutInSecs;
 
-        public RepositoryTracker(PojoServiceRegistry registry, BundleActivator activator, SettableFuture<Repository> repoFuture) {
+        public RepositoryTracker(PojoServiceRegistry registry, BundleActivator activator,
+                                 SettableFuture<Repository> repoFuture, int timeoutInSecs) {
             super(registry.getBundleContext(), Repository.class.getName(), null);
             this.repoFuture = repoFuture;
             this.registry = registry;
             this.activator = activator;
+            this.timeoutInSecs = timeoutInSecs;
             this.open();
         }
 
@@ -394,7 +417,7 @@ public class OakOSGiRepositoryFactory im
             } catch (Exception e) {
                 log.warn("Error occurred while shutting down activator {}", activator.getClass(), e);
             }
-            shutdown(getRegistry());
+            shutdown(getRegistry(), timeoutInSecs);
         }
     }
 

Modified: jackrabbit/oak/trunk/oak-pojosr/src/test/groovy/org/apache/jackrabbit/oak/run/osgi/AbstractRepositoryFactoryTest.groovy
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-pojosr/src/test/groovy/org/apache/jackrabbit/oak/run/osgi/AbstractRepositoryFactoryTest.groovy?rev=1696190&r1=1696189&r2=1696190&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-pojosr/src/test/groovy/org/apache/jackrabbit/oak/run/osgi/AbstractRepositoryFactoryTest.groovy (original)
+++ jackrabbit/oak/trunk/oak-pojosr/src/test/groovy/org/apache/jackrabbit/oak/run/osgi/AbstractRepositoryFactoryTest.groovy Mon Aug 17 04:07:06 2015
@@ -34,7 +34,7 @@ import javax.jcr.*
 import java.util.concurrent.TimeUnit
 
 import static org.apache.jackrabbit.oak.run.osgi.OakOSGiRepositoryFactory.REPOSITORY_HOME
-import static org.apache.jackrabbit.oak.run.osgi.OakOSGiRepositoryFactory.REPOSITORY_STARTUP_TIMEOUT
+import static org.apache.jackrabbit.oak.run.osgi.OakOSGiRepositoryFactory.REPOSITORY_TIMEOUT_IN_SECS
 import static org.apache.jackrabbit.oak.run.osgi.OakOSGiRepositoryFactory.REPOSITORY_BUNDLE_FILTER
 
 abstract class AbstractRepositoryFactoryTest{
@@ -52,7 +52,7 @@ abstract class AbstractRepositoryFactory
         workDir = tmpFolder.getRoot();
         config = [
                 (REPOSITORY_HOME): workDir.absolutePath,
-                (REPOSITORY_STARTUP_TIMEOUT) : 60,
+                (REPOSITORY_TIMEOUT_IN_SECS) : 60,
                 (REPOSITORY_BUNDLE_FILTER) : '''
                             (|
                             (Bundle-SymbolicName=org.apache.jackrabbit*)