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);
+ }
+ }
+}