diff options
author | Stoyan Boshev | 2011-11-17 15:58:33 +0000 |
---|---|---|
committer | Stoyan Boshev | 2011-11-17 15:58:33 +0000 |
commit | 7a03fea698d27f67f32132fc296a996b99c07d32 (patch) | |
tree | 0c7ca9d346b0af6029f92d95a233f54a218db0cd | |
parent | 334028c618932aac912900b5f724e7906ef9f3cc (diff) | |
parent | d578d7448b5581888413617d2aadd5856546a9d6 (diff) | |
download | rt.equinox.bundles-7a03fea698d27f67f32132fc296a996b99c07d32.tar.gz rt.equinox.bundles-7a03fea698d27f67f32132fc296a996b99c07d32.tar.xz rt.equinox.bundles-7a03fea698d27f67f32132fc296a996b99c07d32.zip |
Merge branch 'master' of ssh://sboshev@git.eclipse.org/gitroot/equinox/rt.equinox.bundles.gitv20111117-1558
12 files changed, 256 insertions, 13 deletions
diff --git a/bundles/org.eclipse.equinox.cm/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.cm/META-INF/MANIFEST.MF index f48d842d7..547f2f85c 100644 --- a/bundles/org.eclipse.equinox.cm/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.equinox.cm/META-INF/MANIFEST.MF @@ -7,7 +7,7 @@ Bundle-SymbolicName: org.eclipse.equinox.cm Bundle-Version: 1.0.300.qualifier Bundle-Activator: org.eclipse.equinox.internal.cm.Activator Import-Package: org.osgi.framework;version="1.3.0", - org.osgi.service.cm;version="[1.3,1.4)", + org.osgi.service.cm;version="[1.3,1.5)", org.osgi.service.log;version="1.3.0", org.osgi.service.event;version="1.0"; resolution:=optional, org.osgi.util.tracker;version="1.3.1" diff --git a/bundles/org.eclipse.equinox.compendium.tests/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.compendium.tests/META-INF/MANIFEST.MF index f0557bf73..0c50b1c15 100644 --- a/bundles/org.eclipse.equinox.compendium.tests/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.equinox.compendium.tests/META-INF/MANIFEST.MF @@ -14,7 +14,8 @@ Import-Package: junit.framework;version="3.8.2", org.osgi.service.event;version="1.1.0", org.osgi.service.metatype;version="1.2", org.osgi.service.packageadmin;version="1.2.0", - org.osgi.service.useradmin;version="1.0" + org.osgi.service.useradmin;version="1.0", + org.osgi.service.coordinator;version="1.0" Bundle-RequiredExecutionEnvironment: J2SE-1.4 Bundle-Localization: plugin Bundle-Vendor: %bundleVendor diff --git a/bundles/org.eclipse.equinox.compendium.tests/src/org/eclipse/equinox/compendium/tests/Activator.java b/bundles/org.eclipse.equinox.compendium.tests/src/org/eclipse/equinox/compendium/tests/Activator.java index fb83665fd..a3447abfc 100644 --- a/bundles/org.eclipse.equinox.compendium.tests/src/org/eclipse/equinox/compendium/tests/Activator.java +++ b/bundles/org.eclipse.equinox.compendium.tests/src/org/eclipse/equinox/compendium/tests/Activator.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008, 2010 IBM Corporation and others + * Copyright (c) 2008, 2011 IBM Corporation and others * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -18,6 +18,7 @@ import org.osgi.util.tracker.ServiceTracker; * The activator class controls the plug-in life cycle */ public class Activator implements BundleActivator { + public static String BUNDLE_COORDINATOR = "org.eclipse.equinox.coordinator"; //$NON-NLS-1$ public static String BUNDLE_EVENT = "org.eclipse.equinox.event"; //$NON-NLS-1$ public static String BUNDLE_METATYPE = "org.eclipse.equinox.metatype"; //$NON-NLS-1$ public static String BUNDLE_USERADMIN = "org.eclipse.equinox.useradmin"; //$NON-NLS-1$ diff --git a/bundles/org.eclipse.equinox.compendium.tests/src/org/eclipse/equinox/compendium/tests/AllTests.java b/bundles/org.eclipse.equinox.compendium.tests/src/org/eclipse/equinox/compendium/tests/AllTests.java index 3e612162f..c5e518962 100644 --- a/bundles/org.eclipse.equinox.compendium.tests/src/org/eclipse/equinox/compendium/tests/AllTests.java +++ b/bundles/org.eclipse.equinox.compendium.tests/src/org/eclipse/equinox/compendium/tests/AllTests.java @@ -22,6 +22,7 @@ public class AllTests { suite.addTest(org.eclipse.equinox.metatype.tests.AllTests.suite()); suite.addTest(org.eclipse.equinox.useradmin.tests.AllTests.suite()); suite.addTest(org.eclipse.equinox.event.tests.AllTests.suite()); + suite.addTest(org.eclipse.equinox.coordinator.tests.AllTests.suite()); return suite; } diff --git a/bundles/org.eclipse.equinox.compendium.tests/src/org/eclipse/equinox/coordinator/tests/AllTests.java b/bundles/org.eclipse.equinox.compendium.tests/src/org/eclipse/equinox/coordinator/tests/AllTests.java new file mode 100644 index 000000000..b7d988e77 --- /dev/null +++ b/bundles/org.eclipse.equinox.compendium.tests/src/org/eclipse/equinox/coordinator/tests/AllTests.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * Copyright (c) 2011 IBM Corporation and others + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.coordinator.tests; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class AllTests { + public static Test suite() { + TestSuite suite = new TestSuite("Tests for Equinox Coordinator"); //$NON-NLS-1$ + suite.addTestSuite(CoordinationMaxTimeoutTest.class); + return suite; + } +} diff --git a/bundles/org.eclipse.equinox.compendium.tests/src/org/eclipse/equinox/coordinator/tests/CoordinationMaxTimeoutTest.java b/bundles/org.eclipse.equinox.compendium.tests/src/org/eclipse/equinox/coordinator/tests/CoordinationMaxTimeoutTest.java new file mode 100644 index 000000000..7741d7aa3 --- /dev/null +++ b/bundles/org.eclipse.equinox.compendium.tests/src/org/eclipse/equinox/coordinator/tests/CoordinationMaxTimeoutTest.java @@ -0,0 +1,176 @@ +/******************************************************************************* + * Copyright (c) 2011 IBM Corporation and others + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.coordinator.tests; + +import junit.framework.TestCase; +import org.eclipse.equinox.compendium.tests.Activator; +import org.osgi.framework.ServiceReference; +import org.osgi.service.coordinator.*; + +/* + * Ensures the Coordinator implementation honors a specified maximum timeout + * for coordinations. + * + * https://bugs.eclipse.org/bugs/show_bug.cgi?id=362137 + */ +public class CoordinationMaxTimeoutTest extends TestCase { + private static final long DEVIATION = 500; + private static final String PROPERTY_NAME = "org.eclipse.equinox.coordinator.timeout"; //$NON-NLS-1$ + private static final long TIMEOUT = 5000; + + private Coordinator coordinator; + private ServiceReference coordinatorRef; + + public void testMaxTimeoutWithNoTimeout() throws Exception { + long start = System.currentTimeMillis(); + Coordination c = coordinator.create("c", 0); //$NON-NLS-1$ + try { + assertTimeout(start, TIMEOUT, c); + c.join(10000); + assertTerminated(c); + assertTimeoutDuration(start, TIMEOUT); + } finally { + try { + c.end(); + } catch (CoordinationException e) { + // noop + } + } + } + + public void testMaxTimeoutWithGreaterTimeout() throws Exception { + long start = System.currentTimeMillis(); + Coordination c = coordinator.create("c", 10000); //$NON-NLS-1$ + try { + assertTimeout(start, TIMEOUT, c); + c.join(10000); + assertTerminated(c); + assertTimeoutDuration(start, TIMEOUT); + } finally { + try { + c.end(); + } catch (CoordinationException e) { + // noop + } + } + } + + public void testMaxTimeoutWithLesserTimeout() throws Exception { + long start = System.currentTimeMillis(); + long timeout = 2000; + Coordination c = coordinator.create("c", timeout); //$NON-NLS-1$ + try { + assertTimeout(start, timeout, c); + c.join(5000); + assertTerminated(c); + assertTimeoutDuration(start, timeout); + } finally { + try { + c.end(); + } catch (CoordinationException e) { + // noop + } + } + } + + public void testExtendTimeoutWhenMaxTimeoutAlreadyReached() throws Exception { + long start = System.currentTimeMillis(); + Coordination c = coordinator.create("c", 0); //$NON-NLS-1$ + try { + assertTimeout(start, TIMEOUT, c); + assertEquals("No change in deadline should have occurred", 0, c.extendTimeout(TIMEOUT)); //$NON-NLS-1$ + assertTimeout(start, TIMEOUT, c); + } finally { + try { + c.end(); + } catch (CoordinationException e) { + // noop + } + } + } + + public void testExtendTimeoutWhenMaxTimeoutNotAlreadyReached() throws Exception { + long start = System.currentTimeMillis(); + long timeout = 1500; + Coordination c = coordinator.create("c", timeout); //$NON-NLS-1$ + try { + assertTimeout(start, timeout, c); + c.extendTimeout(timeout); + assertTimeout(start, timeout * 2, c); + c.extendTimeout(TIMEOUT); + assertTimeout(start, TIMEOUT, c); + assertEquals("No change in deadline should have occurred", 0, c.extendTimeout(TIMEOUT)); //$NON-NLS-1$ + assertTimeout(start, TIMEOUT, c); + } finally { + try { + c.end(); + } catch (CoordinationException e) { + // noop + } + } + } + + public void testNoMaxTimeoutWithTimeout() throws Exception { + Activator.getBundleContext().ungetService(coordinatorRef); + System.setProperty(PROPERTY_NAME, String.valueOf(0)); + coordinatorRef = Activator.getBundleContext().getServiceReference(Coordinator.class.getName()); + coordinator = (Coordinator) Activator.getBundleContext().getService(coordinatorRef); + long start = System.currentTimeMillis(); + long timeout = 2000; + Coordination c = coordinator.create("c", timeout); //$NON-NLS-1$ + try { + assertTimeout(start, timeout, c); + c.join(5000); + assertTerminated(c); + assertTimeoutDuration(start, timeout); + } finally { + try { + c.end(); + } catch (CoordinationException e) { + // noop + } + } + } + + protected void setUp() throws Exception { + System.setProperty(PROPERTY_NAME, String.valueOf(TIMEOUT)); + assertSystemProperty(PROPERTY_NAME, String.valueOf(TIMEOUT)); + assertFrameworkProperty(PROPERTY_NAME, String.valueOf(TIMEOUT)); + Activator.getBundle(Activator.BUNDLE_COORDINATOR).start(); + coordinatorRef = Activator.getBundleContext().getServiceReference(Coordinator.class.getName()); + coordinator = (Coordinator) Activator.getBundleContext().getService(coordinatorRef); + } + + protected void tearDown() throws Exception { + Activator.getBundleContext().ungetService(coordinatorRef); + Activator.getBundle(Activator.BUNDLE_COORDINATOR).stop(); + } + + private void assertFrameworkProperty(String name, String value) { + assertEquals("Wrong value for framework property " + name, value, Activator.getBundleContext().getProperty(name)); //$NON-NLS-1$ + } + + private void assertSystemProperty(String name, String value) { + assertEquals("Wrong value for system property " + name, value, System.getProperty(name)); //$NON-NLS-1$ + } + + private void assertTerminated(Coordination c) { + assertTrue("Not terminated", c.isTerminated()); //$NON-NLS-1$ + } + + private void assertTimeout(long start, long timeout, Coordination c) { + assertTrue("Wrong timeout", c.extendTimeout(0) >= start + timeout); //$NON-NLS-1$ + } + + private void assertTimeoutDuration(long start, long timeout) { + assertTrue("Timeout too long", System.currentTimeMillis() - start <= timeout + DEVIATION); //$NON-NLS-1$ + } +} diff --git a/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinationImpl.java b/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinationImpl.java index 3325ae631..ac39a6c56 100644 --- a/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinationImpl.java +++ b/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinationImpl.java @@ -37,6 +37,7 @@ public class CoordinationImpl { private Date deadline; private CoordinationImpl enclosingCoordination; private Thread thread; + private long totalTimeout; private TimerTask timerTask; private final CoordinatorImpl coordinator; @@ -53,7 +54,7 @@ public class CoordinationImpl { validateTimeout(timeout); this.id = id; this.name = name; - this.deadline = new Date(System.currentTimeMillis() + timeout); + totalTimeout = timeout; this.coordinator = coordinator; participants = Collections.synchronizedList(new ArrayList<Participant>()); variables = new HashMap<Class<?>, Object>(); @@ -192,6 +193,25 @@ public class CoordinationImpl { // existing deadline. The deadline will not be null if timerTask is not null. if (timeInMillis == 0) return deadline.getTime(); + long maxTimeout = coordinator.getMaxTimeout(); + long newTotalTimeout = totalTimeout + timeInMillis; + // If there is no maximum timeout, there's no need to track the total timeout. + if (maxTimeout != 0) { + // If the max timeout has already been reached, return 0 indicating that no + // extension has taken place. + if (totalTimeout == maxTimeout) + return 0; + // If the extension would exceed the maximum timeout, add as much time + // as possible. + else if (newTotalTimeout > maxTimeout) { + totalTimeout = maxTimeout; + // Adjust the requested extension amount with the allowable amount. + timeInMillis = newTotalTimeout - maxTimeout; + } + // Otherwise, accept the full extension. + else + totalTimeout = newTotalTimeout; + } // Cancel the current timeout. boolean cancelled = timerTask.cancel(); if (!cancelled) { @@ -338,10 +358,6 @@ public class CoordinationImpl { return referent; } - synchronized Date getDeadline() { - return deadline; - } - LogService getLogService() { return coordinator.getLogService(); } @@ -353,6 +369,8 @@ public class CoordinationImpl { synchronized void setTimerTask(TimerTask timerTask) { this.timerTask = timerTask; + deadline = new Date(System.currentTimeMillis() + totalTimeout); + coordinator.schedule(timerTask, deadline); } synchronized void setThreadAndEnclosingCoordination(Thread t, CoordinationImpl c) { diff --git a/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinatorImpl.java b/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinatorImpl.java index d38ee34d6..94a997a73 100644 --- a/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinatorImpl.java +++ b/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinatorImpl.java @@ -22,6 +22,7 @@ import java.util.Map; import java.util.Timer; import java.util.TimerTask; +import org.eclipse.osgi.util.NLS; import org.osgi.framework.Bundle; import org.osgi.service.coordinator.Coordination; import org.osgi.service.coordinator.CoordinationException; @@ -89,15 +90,19 @@ public class CoordinatorImpl implements Coordinator { private final Bundle bundle; private final List<CoordinationImpl> coordinations; private final LogService logService; + private final long maxTimeout; private final Timer timer; private boolean shutdown; - public CoordinatorImpl(Bundle bundle, LogService logService, Timer timer) { + public CoordinatorImpl(Bundle bundle, LogService logService, Timer timer, long maxTimeout) { this.bundle = bundle; this.logService = logService; this.timer = timer; coordinations = new ArrayList<CoordinationImpl>(); + if (maxTimeout < 0) + throw new IllegalArgumentException(Messages.InvalidTimeInterval); + this.maxTimeout = maxTimeout; } public boolean addParticipant(Participant participant) throws CoordinationException { @@ -119,6 +124,13 @@ public class CoordinatorImpl implements Coordinator { CoordinationWeakReference.processOrphanedCoordinations(); // This method requires the INITIATE permission. No bundle check is done. checkPermission(CoordinationPermission.INITIATE, name); + // Override the requested timeout with the max timeout, if necessary. + if (maxTimeout != 0) { + if (timeout == 0 || maxTimeout < timeout) { + logService.log(LogService.LOG_WARNING, NLS.bind(Messages.MaximumTimeout, timeout, maxTimeout)); + timeout = maxTimeout; + } + } // Create the coordination object itself, which will store its own instance // of a referent to be returned to clients other than the initiator. CoordinationImpl coordination = new CoordinationImpl(getNextId(), name, timeout, this); @@ -141,7 +153,6 @@ public class CoordinatorImpl implements Coordinator { if (timeout > 0) { TimerTask timerTask = new CoordinationTimerTask(coordination); coordination.setTimerTask(timerTask); - schedule(timerTask, coordination.getDeadline()); } // Make sure to return the referent targeted towards the initiator here. return referent; @@ -241,6 +252,10 @@ public class CoordinatorImpl implements Coordinator { LogService getLogService() { return logService; } + + long getMaxTimeout() { + return maxTimeout; + } void purge() { // Purge the timer of all canceled tasks if we're running on a supportive JCL. diff --git a/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinatorServiceFactory.java b/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinatorServiceFactory.java index 86dee1999..a6ff44de0 100644 --- a/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinatorServiceFactory.java +++ b/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinatorServiceFactory.java @@ -19,15 +19,17 @@ import org.osgi.framework.ServiceRegistration; import org.osgi.service.coordinator.Coordinator; public class CoordinatorServiceFactory implements ServiceFactory<Coordinator> { + private final BundleContext bundleContext; private final LogTracker logTracker; private final Timer timer = new Timer(true); public CoordinatorServiceFactory(BundleContext bundleContext) { + this.bundleContext = bundleContext; logTracker = new LogTracker(bundleContext, System.out); } public Coordinator getService(Bundle bundle, ServiceRegistration<Coordinator> registration) { - return new CoordinatorImpl(bundle, logTracker, timer); + return new CoordinatorImpl(bundle, logTracker, timer, getMaxTimeout()); } public void ungetService(Bundle bundle, ServiceRegistration<Coordinator> registration, Coordinator service) { @@ -36,7 +38,12 @@ public class CoordinatorServiceFactory implements ServiceFactory<Coordinator> { void shutdown() { timer.cancel(); -// CoordinatorImpl.reset(); logTracker.close(); } + + private long getMaxTimeout() { + String prop = bundleContext.getProperty("org.eclipse.equinox.coordinator.timeout"); //$NON-NLS-1$ + // Intentionally letting the possible NumberFormatException propagate. + return prop == null ? 0 : Long.parseLong(prop); + } } diff --git a/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/Messages.java b/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/Messages.java index 5070fb3e5..704bb160c 100644 --- a/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/Messages.java +++ b/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/Messages.java @@ -34,6 +34,7 @@ public class Messages extends NLS { public static String CoordinationAlreadyExists; public static String CanceledTaskNotPurged; public static String OrphanedCoordinationError; + public static String MaximumTimeout; static { // initialize resource bundle diff --git a/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/messages.properties b/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/messages.properties index 95b09c271..75aafd831 100644 --- a/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/messages.properties +++ b/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/messages.properties @@ -28,3 +28,4 @@ CoordinatorShutdown=This coordinator has been shutdown CoordinationAlreadyExists=Coordination already exists CanceledTaskNotPurged=Unable to purge the canceled task OrphanedCoordinationError=An error occurred while processing orphaned coordination {0} with ID {1}. +MaximumTimeout=A maximum timeout for coordinations has been set. The requested timeout of {0} will become {1}. diff --git a/bundles/org.eclipse.equinox.ds/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.ds/META-INF/MANIFEST.MF index dc8c88aef..bfc36b796 100644 --- a/bundles/org.eclipse.equinox.ds/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.equinox.ds/META-INF/MANIFEST.MF @@ -21,7 +21,7 @@ Import-Package: org.eclipse.osgi.util, org.osgi.framework;version="1.3", org.osgi.service.cm;version="1.2", - org.osgi.service.component;version="[1.1,1.2)", + org.osgi.service.component;version="[1.1,1.3)", org.osgi.service.log;version="1.3.0", org.osgi.util.tracker;version="1.3", org.apache.felix.scr; version="[1.6,1.7)" |