aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/Activator.java1
-rw-r--r--bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinationImpl.java15
-rw-r--r--bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinationReferent.java104
-rw-r--r--bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinationWeakReference.java68
-rw-r--r--bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinatorImpl.java68
-rw-r--r--bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/Messages.java1
-rw-r--r--bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/messages.properties1
7 files changed, 211 insertions, 47 deletions
diff --git a/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/Activator.java b/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/Activator.java
index eceb8dc7..86ae4b35 100644
--- a/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/Activator.java
+++ b/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/Activator.java
@@ -43,5 +43,6 @@ public class Activator implements BundleActivator {
if (registration != null)
registration.unregister();
factory.shutdown();
+ CoordinationWeakReference.processOrphanedCoordinations();
}
}
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 bfc28391..05236274 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
@@ -10,7 +10,6 @@
*******************************************************************************/
package org.eclipse.equinox.coordinator;
-import java.lang.ref.Reference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
@@ -31,7 +30,7 @@ public class CoordinationImpl implements Coordination {
private volatile boolean terminated;
private Date deadline;
- private Reference<CoordinationImpl> enclosingCoordination;
+ private CoordinationImpl enclosingCoordination;
private Thread thread;
private TimerTask timerTask;
@@ -127,7 +126,7 @@ public class CoordinationImpl implements Coordination {
}
// Unwind the stack in case there are other coordinations higher
// up than this one.
- while (coordinator.peek() != this) {
+ while (!coordinator.peek().equals(this)) {
try {
coordinator.peek().end();
} catch (CoordinationException e) {
@@ -146,9 +145,10 @@ public class CoordinationImpl implements Coordination {
Exception exception = null;
// No additional synchronization is needed here because the participant
// list will not be modified post termination.
+ CoordinationReferent referent = new CoordinationReferent(this);
for (Participant participant : participants) {
try {
- participant.ended(this);
+ participant.ended(referent);
} catch (Exception e) {
coordinator.getLogService().log(LogService.LOG_WARNING, Messages.CoordinationImpl_4, e);
// Only the first exception will be propagated.
@@ -232,9 +232,10 @@ public class CoordinationImpl implements Coordination {
// Notify participants this coordination has failed.
// No additional synchronization is needed here because the participant
// list will not be modified post termination.
+ CoordinationReferent referent = new CoordinationReferent(this);
for (Participant participant : participants) {
try {
- participant.failed(this);
+ participant.failed(referent);
} catch (Exception e) {
coordinator.getLogService().log(LogService.LOG_WARNING, Messages.CoordinationImpl_6, e);
}
@@ -254,7 +255,7 @@ public class CoordinationImpl implements Coordination {
public synchronized Coordination getEnclosingCoordination() {
coordinator.checkPermission(CoordinationPermission.ADMIN, name);
- return enclosingCoordination == null ? null : enclosingCoordination.get();
+ return enclosingCoordination;
}
public Throwable getFailure() {
@@ -329,7 +330,7 @@ public class CoordinationImpl implements Coordination {
this.timerTask = timerTask;
}
- synchronized void setThreadAndEnclosingCoordination(Thread t, Reference<CoordinationImpl> c) {
+ synchronized void setThreadAndEnclosingCoordination(Thread t, CoordinationImpl c) {
thread = t;
enclosingCoordination = c;
}
diff --git a/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinationReferent.java b/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinationReferent.java
new file mode 100644
index 00000000..68b807d8
--- /dev/null
+++ b/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinationReferent.java
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ * 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;
+
+import java.util.List;
+import java.util.Map;
+
+import org.osgi.framework.Bundle;
+import org.osgi.service.coordinator.Coordination;
+import org.osgi.service.coordinator.Participant;
+
+public class CoordinationReferent implements Coordination {
+ private final CoordinationImpl coordination;
+
+ public CoordinationReferent(CoordinationImpl coordination) {
+ if (coordination == null)
+ throw new NullPointerException();
+ this.coordination = coordination;
+ }
+
+ public long getId() {
+ return coordination.getId();
+ }
+
+ public String getName() {
+ return coordination.getName();
+ }
+
+ public void end() {
+ coordination.end();
+ }
+
+ public boolean fail(Throwable cause) {
+ return coordination.fail(cause);
+ }
+
+ public Throwable getFailure() {
+ return coordination.getFailure();
+ }
+
+ public boolean isTerminated() {
+ return coordination.isTerminated();
+ }
+
+ public void addParticipant(Participant participant) {
+ coordination.addParticipant(participant);
+ }
+
+ public List<Participant> getParticipants() {
+ return coordination.getParticipants();
+ }
+
+ public Map<Class<?>, Object> getVariables() {
+ return coordination.getVariables();
+ }
+
+ public long extendTimeout(long timeMillis) {
+ return coordination.extendTimeout(timeMillis);
+ }
+
+ public void join(long timeMillis) throws InterruptedException {
+ coordination.join(timeMillis);
+ }
+
+ public Coordination push() {
+ return coordination.push();
+ }
+
+ public Thread getThread() {
+ return coordination.getThread();
+ }
+
+ public Bundle getBundle() {
+ return coordination.getBundle();
+ }
+
+ public Coordination getEnclosingCoordination() {
+ return coordination.getEnclosingCoordination();
+ }
+
+ @Override
+ public boolean equals(Object object) {
+ if (object instanceof CoordinationReferent)
+ return coordination.equals(((CoordinationReferent)object).coordination);
+ return coordination.equals(object);
+ }
+
+ @Override
+ public int hashCode() {
+ return coordination.hashCode();
+ }
+
+ CoordinationImpl getDelegate() {
+ return coordination;
+ }
+}
diff --git a/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinationWeakReference.java b/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinationWeakReference.java
new file mode 100644
index 00000000..0442c38f
--- /dev/null
+++ b/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinationWeakReference.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * 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;
+
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.eclipse.osgi.util.NLS;
+import org.osgi.service.coordinator.Coordination;
+import org.osgi.service.coordinator.CoordinationException;
+import org.osgi.service.log.LogService;
+
+public class CoordinationWeakReference extends WeakReference<CoordinationReferent> {
+ private static final ReferenceQueue<CoordinationReferent> referenceQueue = new ReferenceQueue<CoordinationReferent>();
+ private static final Set<CoordinationWeakReference> references = Collections.synchronizedSet(new HashSet<CoordinationWeakReference>());
+
+ public static CoordinationWeakReference newInstance(CoordinationReferent referent) {
+ CoordinationWeakReference reference = new CoordinationWeakReference(referent);
+ references.add(reference);
+ return reference;
+ }
+
+ public static void processOrphanedCoordinations() {
+ CoordinationWeakReference r;
+ while ((r = (CoordinationWeakReference)referenceQueue.poll()) != null) {
+ references.remove(r);
+ CoordinationImpl c = r.getCoordination();
+ try {
+ c.fail(Coordination.ORPHANED);
+ }
+ catch (Throwable t) {
+ c.getLogService().log(LogService.LOG_ERROR, NLS.bind(Messages.CoordinatorImpl_5, c.getName(), c.getId()), t);
+ }
+ finally {
+ try {
+ c.end();
+ }
+ catch (CoordinationException e) {
+ // This is expected since we already failed the coordination.
+ }
+ }
+ }
+ }
+
+ private final CoordinationImpl coordination;
+
+ private CoordinationWeakReference(CoordinationReferent referent) {
+ super(referent, referenceQueue);
+ coordination = referent.getDelegate();
+ if (coordination == null)
+ throw new NullPointerException();
+ }
+
+ public CoordinationImpl getCoordination() {
+ return coordination;
+ }
+}
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 4060b66b..e143240f 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
@@ -10,9 +10,6 @@
*******************************************************************************/
package org.eclipse.equinox.coordinator;
-import java.lang.ref.Reference;
-import java.lang.ref.ReferenceQueue;
-import java.lang.ref.WeakReference;
import java.security.Permission;
import java.util.ArrayList;
import java.util.Collection;
@@ -57,59 +54,35 @@ public class CoordinatorImpl implements Coordinator {
};
private static class WeakCoordinationStack {
- private final LinkedList<Reference<CoordinationImpl>> coordinations = new LinkedList<Reference<CoordinationImpl>>();
- private final ReferenceQueue<CoordinationImpl> queue = new ReferenceQueue<CoordinationImpl>();
+ private final LinkedList<CoordinationImpl> coordinations = new LinkedList<CoordinationImpl>();
public WeakCoordinationStack() {
}
public boolean contains(CoordinationImpl c) {
- purge();
- for (Reference<CoordinationImpl> r : coordinations) {
- if (c.equals(r.get()))
- return true;
- }
- return false;
+ return coordinations.contains(c);
}
public CoordinationImpl peek() {
- purge();
if (coordinations.isEmpty())
return null;
- return coordinations.getFirst().get();
+ return coordinations.getFirst();
}
public CoordinationImpl pop() {
- purge();
if (coordinations.isEmpty())
return null;
- CoordinationImpl c = coordinations.removeFirst().get();
+ CoordinationImpl c = coordinations.removeFirst();
if (c != null)
c.setThreadAndEnclosingCoordination(null, null);
return c;
}
public void push(CoordinationImpl c) {
- purge();
if (contains(c))
throw new CoordinationException(Messages.CoordinatorImpl_3, c, CoordinationException.ALREADY_PUSHED);
- Reference<CoordinationImpl> r = new WeakReference<CoordinationImpl>(c, queue);
c.setThreadAndEnclosingCoordination(Thread.currentThread(), coordinations.isEmpty() ? null : coordinations.getFirst());
- coordinations.addFirst(r);
- }
-
- private void purge() {
- Reference<? extends CoordinationImpl> r;
- while ((r = queue.poll()) != null) {
- int index = coordinations.indexOf(r);
- coordinations.remove(r);
- if (index > 0) {
- r = coordinations.get(index - 1);
- CoordinationImpl c = r.get();
- if (c != null)
- c.setThreadAndEnclosingCoordination(Thread.currentThread(), coordinations.get(index));
- }
- }
+ coordinations.addFirst(c);
}
}
@@ -128,6 +101,7 @@ public class CoordinatorImpl implements Coordinator {
}
public boolean addParticipant(Participant participant) throws CoordinationException {
+ CoordinationWeakReference.processOrphanedCoordinations();
Coordination coordination = peek();
if (coordination == null)
return false;
@@ -136,19 +110,22 @@ public class CoordinatorImpl implements Coordinator {
}
public Coordination begin(String name, long timeout) {
- CoordinationImpl coordination = (CoordinationImpl) create(name, timeout);
+ Coordination coordination = create(name, timeout);
coordination.push();
return coordination;
}
public Coordination create(String name, long timeout) {
+ CoordinationWeakReference.processOrphanedCoordinations();
// This method requires the INITIATE permission. No bundle check is done.
checkPermission(CoordinationPermission.INITIATE, name);
CoordinationImpl coordination = new CoordinationImpl(getNextId(), name, timeout, this);
+ CoordinationReferent referent = new CoordinationReferent(coordination);
synchronized (this) {
if (shutdown)
throw new IllegalStateException(Messages.CoordinatorImpl_2);
synchronized (CoordinatorImpl.class) {
+ CoordinationWeakReference.newInstance(referent);
coordinations.add(coordination);
idToCoordination.put(new Long(coordination.getId()), coordination);
}
@@ -158,10 +135,11 @@ public class CoordinatorImpl implements Coordinator {
coordination.setTimerTask(timerTask);
schedule(timerTask, coordination.getDeadline());
}
- return coordination;
+ return referent;
}
public boolean fail(Throwable reason) {
+ CoordinationWeakReference.processOrphanedCoordinations();
Coordination coordination = peek();
if (coordination == null)
return false;
@@ -169,9 +147,12 @@ public class CoordinatorImpl implements Coordinator {
}
public Coordination getCoordination(long id) {
- CoordinationImpl result = null;
+ CoordinationWeakReference.processOrphanedCoordinations();
+ CoordinationReferent result = null;
synchronized (CoordinatorImpl.class) {
- result = idToCoordination.get(new Long(id));
+ CoordinationImpl c = idToCoordination.get(new Long(id));
+ if (c != null)
+ result = new CoordinationReferent(c);
}
if (result != null && !result.isTerminated()) {
try {
@@ -185,6 +166,7 @@ public class CoordinatorImpl implements Coordinator {
}
public Collection<Coordination> getCoordinations() {
+ CoordinationWeakReference.processOrphanedCoordinations();
ArrayList<Coordination> result;
synchronized (CoordinatorImpl.class) {
result = new ArrayList<Coordination>(idToCoordination.size());
@@ -195,7 +177,7 @@ public class CoordinatorImpl implements Coordinator {
continue;
try {
checkPermission(CoordinationPermission.ADMIN, coordination.getName());
- result.add(coordination);
+ result.add(new CoordinationReferent(coordination));
} catch (SecurityException e) {
logService.log(LogService.LOG_DEBUG, Messages.CoordinatorImpl_1, e);
}
@@ -206,14 +188,19 @@ public class CoordinatorImpl implements Coordinator {
}
public Coordination peek() {
- return coordinationStack.get().peek();
+ CoordinationWeakReference.processOrphanedCoordinations();
+ CoordinationImpl c = coordinationStack.get().peek();
+ if (c == null)
+ return null;
+ return new CoordinationReferent(c);
}
public Coordination pop() {
- Coordination c = coordinationStack.get().peek();
+ CoordinationWeakReference.processOrphanedCoordinations();
+ CoordinationImpl c = coordinationStack.get().peek();
if (c == null) return null;
checkPermission(CoordinationPermission.INITIATE, c.getName());
- return coordinationStack.get().pop();
+ return new CoordinationReferent(coordinationStack.get().pop());
}
CoordinationImpl addParticipant(Participant participant, CoordinationImpl coordination) {
@@ -264,6 +251,7 @@ public class CoordinatorImpl implements Coordinator {
}
void shutdown() {
+ CoordinationWeakReference.processOrphanedCoordinations();
List<Coordination> coords;
synchronized (this) {
shutdown = true;
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 bb520588..6603c510 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
@@ -35,6 +35,7 @@ public class Messages extends NLS {
public static String CoordinatorImpl_2;
public static String CoordinatorImpl_3;
public static String CoordinatorImpl_4;
+ public static String CoordinatorImpl_5;
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 bf1e76e4..d3ca6814 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
@@ -29,3 +29,4 @@ CoordinatorImpl_1=A requestor did not have permission to view a coordination
CoordinatorImpl_2=This coordinator has been shutdown
CoordinatorImpl_3=Coordination already exists
CoordinatorImpl_4=Unable to purge the canceled task
+CoordinatorImpl_5=An error occurred while failing coordination {0} with ID {1}.