You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by ff...@apache.org on 2012/10/31 01:33:41 UTC

svn commit: r1403940 - in /karaf/trunk/main/src: main/java/org/apache/karaf/main/Main.java main/java/org/apache/karaf/main/lock/LockManager.java test/java/org/apache/karaf/main/MainLockingTest.java test/java/org/apache/karaf/main/MockLock.java

Author: ffang
Date: Wed Oct 31 00:33:40 2012
New Revision: 1403940

URL: http://svn.apache.org/viewvc?rev=1403940&view=rev
Log:
[KARAF-1938]Lock logic should wait for start level change to occur 

Added:
    karaf/trunk/main/src/test/java/org/apache/karaf/main/MainLockingTest.java
    karaf/trunk/main/src/test/java/org/apache/karaf/main/MockLock.java
Modified:
    karaf/trunk/main/src/main/java/org/apache/karaf/main/Main.java
    karaf/trunk/main/src/main/java/org/apache/karaf/main/lock/LockManager.java

Modified: karaf/trunk/main/src/main/java/org/apache/karaf/main/Main.java
URL: http://svn.apache.org/viewvc/karaf/trunk/main/src/main/java/org/apache/karaf/main/Main.java?rev=1403940&r1=1403939&r2=1403940&view=diff
==============================================================================
--- karaf/trunk/main/src/main/java/org/apache/karaf/main/Main.java (original)
+++ karaf/trunk/main/src/main/java/org/apache/karaf/main/Main.java Wed Oct 31 00:33:40 2012
@@ -50,6 +50,7 @@ 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;
 import org.osgi.framework.launch.Framework;
 import org.osgi.framework.launch.FrameworkFactory;
 import org.osgi.framework.startlevel.BundleStartLevel;
@@ -215,7 +216,8 @@ public class Main {
         }
         BootstrapLogManager.setProperties(config.props);
         Lock lock = createLock();
-        lockManager = new LockManager(lock, new KarafLockCallback(), config.lockDelay);
+        KarafLockCallback lockCallback = new KarafLockCallback();
+        lockManager = new LockManager(lock, lockCallback, config.lockDelay);
         InstanceHelper.updateInstancePid(config.karafHome, config.karafBase);
         LOG.addHandler(BootstrapLogManager.getDefaultHandler());
 
@@ -231,6 +233,7 @@ public class Main {
         FrameworkFactory factory = loadFrameworkFactory(classLoader);
         framework = factory.newFramework(new StringMap(config.props, false));
         framework.init();
+        framework.getBundleContext().addFrameworkListener(lockCallback);
         framework.start();
 
         FrameworkStartLevel sl = framework.adapt(FrameworkStartLevel.class);
@@ -472,12 +475,30 @@ public class Main {
         }
     }
     
-    private final class KarafLockCallback implements LockCallBack {
+    public LockManager getLockManager() {
+        return lockManager;
+    }
+
+    private final class KarafLockCallback implements LockCallBack, FrameworkListener {
+        private Object startLevelLock = new Object();
+
         @Override
         public void lockLost() {
             if (framework.getState() == Bundle.ACTIVE) {
                 LOG.warning("Lock lost. Setting startlevel to " + config.lockStartLevel);
-                setStartLevel(config.lockStartLevel);
+                synchronized (startLevelLock) {
+                    setStartLevel(config.lockStartLevel);
+
+                    // we have to wait for the start level to be reduced here because
+                    // if the lock is regained before the start level is fully changed
+                    // things may not come up as expected
+                    LOG.fine("Waiting for start level change to complete...");
+                    try {
+                        startLevelLock.wait(config.shutdownTimeout);
+                    } catch (InterruptedException e) {
+                        e.printStackTrace();
+                    }
+                }
             }
         }
 
@@ -492,6 +513,16 @@ public class Main {
         public void waitingForLock() {
             LOG.fine("Waiting for the lock ...");
         }
+
+        @Override
+        public void frameworkEvent(FrameworkEvent event) {
+            if (event.getType() == FrameworkEvent.STARTLEVEL_CHANGED) {
+                synchronized (startLevelLock) {
+                    LOG.fine("Start level change complete.");
+                    startLevelLock.notifyAll();
+                }
+            }
+       }
     }
 
 }

Modified: karaf/trunk/main/src/main/java/org/apache/karaf/main/lock/LockManager.java
URL: http://svn.apache.org/viewvc/karaf/trunk/main/src/main/java/org/apache/karaf/main/lock/LockManager.java?rev=1403940&r1=1403939&r2=1403940&view=diff
==============================================================================
--- karaf/trunk/main/src/main/java/org/apache/karaf/main/lock/LockManager.java (original)
+++ karaf/trunk/main/src/main/java/org/apache/karaf/main/lock/LockManager.java Wed Oct 31 00:33:40 2012
@@ -85,4 +85,7 @@ public class LockManager {
         lock.release();
     }
 
+    public Lock getLock() {
+        return lock;
+    }
 }

Added: karaf/trunk/main/src/test/java/org/apache/karaf/main/MainLockingTest.java
URL: http://svn.apache.org/viewvc/karaf/trunk/main/src/test/java/org/apache/karaf/main/MainLockingTest.java?rev=1403940&view=auto
==============================================================================
--- karaf/trunk/main/src/test/java/org/apache/karaf/main/MainLockingTest.java (added)
+++ karaf/trunk/main/src/test/java/org/apache/karaf/main/MainLockingTest.java Wed Oct 31 00:33:40 2012
@@ -0,0 +1,95 @@
+/*
+ * 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.karaf.main;
+
+import static org.ops4j.pax.tinybundles.core.TinyBundles.withBnd;
+
+import java.io.File;
+
+import junit.framework.Assert;
+
+import org.apache.karaf.main.util.Utils;
+import org.junit.Test;
+import org.ops4j.pax.tinybundles.core.TinyBundles;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+import org.osgi.framework.launch.Framework;
+import org.osgi.framework.startlevel.FrameworkStartLevel;
+
+public class MainLockingTest {
+    
+    @Test
+    public void testLostMasterLock() throws Exception {
+        File basedir = new File(getClass().getClassLoader().getResource("foo").getPath()).getParentFile();
+        File home = new File(basedir, "test-karaf-home");
+        File data = new File(home, "data");
+
+        Utils.deleteDirectory(data);
+
+                String[] args = new String[0];
+                System.setProperty("karaf.home", home.toString());
+                System.setProperty("karaf.data", data.toString());
+        System.setProperty("karaf.framework.factory", "org.apache.felix.framework.FrameworkFactory");
+
+        System.setProperty("karaf.lock","true");
+        System.setProperty("karaf.lock.delay","1000");
+        System.setProperty("karaf.lock.class","org.apache.karaf.main.MockLock");
+
+        Main main = new Main(args);
+        main.launch();
+        Framework framework = main.getFramework();
+        String activatorName = TimeoutShutdownActivator.class.getName().replace('.', '/') + ".class";
+        Bundle bundle = framework.getBundleContext().installBundle("foo",
+                TinyBundles.bundle()
+                    .set( Constants.BUNDLE_ACTIVATOR, TimeoutShutdownActivator.class.getName() )
+                    .add( activatorName, getClass().getClassLoader().getResourceAsStream( activatorName ) )
+                    .build( withBnd() )
+        );
+        
+        bundle.start();       
+        
+        Thread.sleep(2000);
+        
+        FrameworkStartLevel sl = framework.adapt(FrameworkStartLevel.class);
+        
+        MockLock lock = (MockLock) main.getLockManager().getLock();        
+
+        Assert.assertEquals(100, sl.getStartLevel());       
+
+        // simulate losing a lock
+        lock.setIsAlive(false);
+        lock.setLock(false);
+        
+        // lets wait until the start level change is complete
+        lock.waitForLock();
+        Assert.assertEquals(1, sl.getStartLevel());
+
+        Thread.sleep(1000);
+        
+        // get lock back
+        lock.setIsAlive(true);
+        lock.setLock(true);
+
+        
+        Thread.sleep(1000);
+        
+        // exit framework + lock loop
+        main.destroy();
+    }    
+}

Added: karaf/trunk/main/src/test/java/org/apache/karaf/main/MockLock.java
URL: http://svn.apache.org/viewvc/karaf/trunk/main/src/test/java/org/apache/karaf/main/MockLock.java?rev=1403940&view=auto
==============================================================================
--- karaf/trunk/main/src/test/java/org/apache/karaf/main/MockLock.java (added)
+++ karaf/trunk/main/src/test/java/org/apache/karaf/main/MockLock.java Wed Oct 31 00:33:40 2012
@@ -0,0 +1,66 @@
+package org.apache.karaf.main;
+
+import java.util.Properties;
+import java.util.logging.Logger;
+
+import org.apache.karaf.main.lock.Lock;
+
+/*
+ * 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.
+ */
+public class MockLock implements Lock {
+
+    private boolean lock = true;
+    private boolean isAlive = true; 
+    private static final Logger LOG = Logger.getLogger(MockLock.class.getName());
+    private Object lockLock = new Object();
+    
+    public MockLock(Properties props) {
+    }
+    
+    public boolean lock() throws Exception {
+        synchronized (lockLock) {
+            LOG.fine("lock = " + lock);        
+            lockLock.notifyAll();
+        }
+        return lock;
+    }
+
+    public void release() throws Exception {
+        LOG.fine("release");
+    }
+
+    public boolean isAlive() throws Exception {
+        LOG.fine("isAlive = " + isAlive);
+        return isAlive;
+    }
+
+    public void setLock(boolean lock) {
+        this.lock = lock;
+    }
+
+    public void setIsAlive(boolean isAlive) {
+        this.isAlive = isAlive;
+    }
+    
+    public void waitForLock() throws InterruptedException {
+        synchronized (lockLock) {
+            lockLock.wait(1000 * 60 * 5);
+        }
+    }
+}