diff options
author | John Ross | 2011-11-17 11:47:50 +0000 |
---|---|---|
committer | John Ross | 2011-11-17 11:50:37 +0000 |
commit | 85bfc05eb6f0efe5416b57ae7e925f3a1000686f (patch) | |
tree | d4ea52a94ac5d02c49a0a4b78842ddfda16f8156 | |
parent | ff55d9968fcc1526a8df8bbd78cf291b3a657b93 (diff) | |
download | rt.equinox.bundles-85bfc05eb6f0efe5416b57ae7e925f3a1000686f.tar.gz rt.equinox.bundles-85bfc05eb6f0efe5416b57ae7e925f3a1000686f.tar.xz rt.equinox.bundles-85bfc05eb6f0efe5416b57ae7e925f3a1000686f.zip |
Bug 362137: Support for coordination maximum timeout.v20111117-1150
I added support for a new property named
org.eclipse.equinox.coordinator.timeout. The value is in milliseconds. The
default value is 0.
The property is retrieved using the coordinator's BundleContext.getProperty.
The property is retrieved anew with each instantiation of a Coordinator
service.
If a client attempts to create a coordination with a timeout less than the
maximum timeout (when max timeout != 0), the requested timeout will be
overwritten with the max timeout. If max timeout != 0, clients will not be able
to extend the timeout of a coordination beyond the max.
5 files changed, 51 insertions, 9 deletions
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}. |