You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by jw...@apache.org on 2012/02/18 00:17:51 UTC
svn commit: r1245802 - in
/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal:
AriesSubsystem.java SubsystemGraph.java SubsystemServiceRegistrar.java
Author: jwross
Date: Fri Feb 17 23:17:51 2012
New Revision: 1245802
URL: http://svn.apache.org/viewvc?rev=1245802&view=rev
Log:
ARIES-825: Update subsystems to latest Subsystem, Resolver, and Repository APIs.
(1) now fails install if a cycle is detected in the subsystem graph
(2) added INSTALL_FAILED to list of uninstall states that simply return
Added:
aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemGraph.java
Modified:
aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/AriesSubsystem.java
aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemServiceRegistrar.java
Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/AriesSubsystem.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/AriesSubsystem.java?rev=1245802&r1=1245801&r2=1245802&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/AriesSubsystem.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/AriesSubsystem.java Fri Feb 17 23:17:51 2012
@@ -206,14 +206,13 @@ public class AriesSubsystem implements S
}
private final SubsystemArchive archive;
- private final Set<AriesSubsystem> children = Collections.synchronizedSet(new HashSet<AriesSubsystem>());
private final Set<Resource> constituents = Collections.synchronizedSet(new HashSet<Resource>());
private final File directory;
private final SubsystemEnvironment environment;
private final long id;
private final String location;
- private final Set<AriesSubsystem> parents = Collections.synchronizedSet(new HashSet<AriesSubsystem>());
private final Region region;
+ private final SubsystemGraph subsystemGraph;
private boolean autostart;
private Subsystem.State state = State.INSTALLING;
@@ -252,6 +251,8 @@ public class AriesSubsystem implements S
// on any persisted resources.
subsystemManifest = new SubsystemManifest(getSymbolicName(), getVersion(), archive.getResources());
environment = new SubsystemEnvironment(this);
+ // The root subsystem establishes the subsystem graph;
+ subsystemGraph = new SubsystemGraph(this);
archive.setDeploymentManifest(new DeploymentManifest(
deploymentManifest,
subsystemManifest,
@@ -295,7 +296,6 @@ public class AriesSubsystem implements S
}
this.location = location;
- this.parents.add(parent);
id = getNextId();
String directoryName = "subsystem" + id;
// TODO Add to constants.
@@ -327,6 +327,7 @@ public class AriesSubsystem implements S
deleteFile(zipFile);
throw new SubsystemException(e);
}
+ subsystemGraph = parent.subsystemGraph;
}
public AriesSubsystem(SubsystemArchive archive, AriesSubsystem parent) throws Exception {
@@ -340,12 +341,12 @@ public class AriesSubsystem implements S
String directoryName = "subsystem" + id;
directory = new File(parent.directory, directoryName);
environment = new SubsystemEnvironment(this);
- parents.add(parent);
// Unscoped subsystems don't get their own region. They share the region with their scoped parent.
if (isFeature())
region = parent.region;
else
region = createRegion(getSymbolicName() + ';' + getVersion() + ';' + getType() + ';' + getSubsystemId());
+ subsystemGraph = parent.subsystemGraph;
}
public SubsystemArchive getArchive() {
@@ -380,9 +381,9 @@ public class AriesSubsystem implements S
return Collections.emptyList();
}
- @SuppressWarnings({ "unchecked", "rawtypes" })
+ @Override
public Collection<Subsystem> getChildren() {
- return (Collection<Subsystem>)(Collection)Collections.unmodifiableCollection(new ArrayList<Subsystem>(children));
+ return subsystemGraph.getChildren(this);
}
@Override
@@ -397,7 +398,7 @@ public class AriesSubsystem implements S
@Override
public Collection<Subsystem> getParents() {
- return Collections.unmodifiableCollection(new ArrayList<Subsystem>(parents));
+ return subsystemGraph.getParents(this);
}
@Override
@@ -460,7 +461,7 @@ public class AriesSubsystem implements S
&& subsystem.getVersion().equals(ssr.getSubsystemVersion())
&& subsystem.getType().equals(ssr.getSubsystemType())))
throw new SubsystemException("Location already exists but symbolic name, version, and type are not the same: " + location);
- children.add(subsystem);
+ subsystemGraph.add(this, subsystem);
constituents.add(subsystem);
return subsystem;
}
@@ -468,7 +469,7 @@ public class AriesSubsystem implements S
if (subsystem != null) {
if (!subsystem.getType().equals(ssr.getSubsystemType()))
throw new SubsystemException("Subsystem already exists in target region but has a different type: " + location);
- children.add(subsystem);
+ subsystemGraph.add(this, subsystem);
constituents.add(subsystem);
return subsystem;
}
@@ -562,7 +563,6 @@ public class AriesSubsystem implements S
startResource(resource, coordination);
}
setState(State.ACTIVE);
-// persist(State.ACTIVE);
} catch (Exception e) {
coordination.fail(e);
// TODO Need to reinstate complete isolation by disconnecting the
@@ -614,7 +614,7 @@ public class AriesSubsystem implements S
// The root subsystem may not be uninstalled.
checkRoot();
State state = getState();
- if (state == State.UNINSTALLING || state == State.UNINSTALLED) {
+ if (state == State.UNINSTALLING || state == State.UNINSTALLED || state == State.INSTALL_FAILED) {
return;
}
else if (state == State.INSTALLING || state == State.RESOLVING || state == State.STARTING || state == State.STOPPING) {
@@ -649,10 +649,10 @@ public class AriesSubsystem implements S
// TODO Should FAILED go out for each failure?
}
}
- for (AriesSubsystem parent : parents) {
- parent.children.remove(this);
- parent.constituents.remove(this);
+ for (Subsystem parent : getParents()) {
+ ((AriesSubsystem)parent).constituents.remove(this);
}
+ subsystemGraph.remove(this);
locationToSubsystem.remove(location);
deleteFile(directory);
setState(State.UNINSTALLED);
@@ -780,9 +780,9 @@ public class AriesSubsystem implements S
}
setState(State.STOPPING);
// Stop child subsystems first.
- for (AriesSubsystem subsystem : children) {
+ for (Subsystem subsystem : subsystemGraph.getChildren(this)) {
try {
- stopSubsystemResource(subsystem);
+ stopSubsystemResource((AriesSubsystem)subsystem);
}
catch (Exception e) {
LOGGER.error("An error occurred while stopping resource "
@@ -898,8 +898,8 @@ public class AriesSubsystem implements S
if (transitive) {
// Transitive dependencies should be provisioned into the highest possible level.
// TODO Assumes root is always the appropriate level.
- while (!provisionTo.parents.isEmpty())
- provisionTo = provisionTo.parents.iterator().next();
+ while (!provisionTo.getParents().isEmpty())
+ provisionTo = (AriesSubsystem)provisionTo.getParents().iterator().next();
}
return provisionTo;
}
@@ -991,7 +991,7 @@ public class AriesSubsystem implements S
Set<AriesSubsystem> subsystems = new HashSet<AriesSubsystem>();
subsystems.add(this);
resourceToSubsystems.put(subsystem, subsystems);
- children.add(subsystem);
+ subsystemGraph.add(this, subsystem);
constituents.add(subsystem);
subsystem.install();
coordination.addParticipant(new Participant() {
@@ -1002,7 +1002,6 @@ public class AriesSubsystem implements S
public void failed(Coordination coordination) throws Exception {
subsystem.uninstall();
constituents.remove(subsystem);
- children.remove(subsystem);
Set<AriesSubsystem> subsystems = resourceToSubsystems.get(subsystem);
subsystems.remove(AriesSubsystem.this);
if (subsystems.isEmpty())
@@ -1063,7 +1062,7 @@ public class AriesSubsystem implements S
// Applications have an implicit import policy equating to "import everything that I require", which is not the same as features.
// This must be computed from the application requirements and will be done using the Wires returned by the Resolver, when one is available.
region.connectRegion(
- parents.iterator().next().region,
+ ((AriesSubsystem)getParents().iterator().next()).region,
region.getRegionDigraph().createRegionFilterBuilder().allowAll(RegionFilter.VISIBLE_ALL_NAMESPACE).build());
}
else if (isComposite()) {
Added: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemGraph.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemGraph.java?rev=1245802&view=auto
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemGraph.java (added)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemGraph.java Fri Feb 17 23:17:51 2012
@@ -0,0 +1,126 @@
+package org.apache.aries.subsystem.core.internal;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.osgi.service.subsystem.Subsystem;
+import org.osgi.service.subsystem.SubsystemException;
+
+public class SubsystemGraph {
+ private static class SubsystemWrapper {
+ private final Subsystem s;
+
+ public SubsystemWrapper(Subsystem subsystem) {
+ s = subsystem;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == this)
+ return true;
+ if (!(o instanceof SubsystemWrapper))
+ return false;
+ SubsystemWrapper that = (SubsystemWrapper)o;
+ return s.getSymbolicName().equals(that.s.getSymbolicName())
+ && s.getVersion().equals(that.s.getVersion())
+ && s.getType().equals(that.s.getType());
+ }
+
+ public Subsystem getSubsystem() {
+ return s;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 17;
+ result = result + 31 * s.getSymbolicName().hashCode();
+ result = result + 31 * s.getVersion().hashCode();
+ result = result + 31 * s.getType().hashCode();
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return new StringBuilder().append(s.getClass().getName())
+ .append(": symbolicName=").append(s.getSymbolicName())
+ .append(", version=").append(s.getVersion())
+ .append(", type=").append(s.getType()).toString();
+ }
+ }
+ private final Map<SubsystemWrapper, Collection<SubsystemWrapper>> adjacencyList = new HashMap<SubsystemWrapper, Collection<SubsystemWrapper>>();
+
+ public SubsystemGraph(Subsystem root) {
+ adjacencyList.put(new SubsystemWrapper(root), new HashSet<SubsystemWrapper>());
+ }
+
+ public synchronized void add(Subsystem parent, Subsystem child) {
+ SubsystemWrapper parentWrap = new SubsystemWrapper(parent);
+ SubsystemWrapper childWrap = new SubsystemWrapper(child);
+ if (containsAncestor(childWrap, parentWrap))
+ throw new SubsystemException("Cycle detected between '" + parentWrap + "' and '" + childWrap + "'");
+ Collection<SubsystemWrapper> subsystems = adjacencyList.get(childWrap);
+ if (subsystems == null) {
+ subsystems = new HashSet<SubsystemWrapper>();
+ adjacencyList.put(childWrap, subsystems);
+ }
+ subsystems = adjacencyList.get(parentWrap);
+ if (subsystems == null) {
+ subsystems = new HashSet<SubsystemWrapper>();
+ adjacencyList.put(parentWrap, subsystems);
+ }
+ subsystems.add(childWrap);
+ }
+
+ public synchronized Collection<Subsystem> getChildren(Subsystem parent) {
+ Collection<SubsystemWrapper> children = adjacencyList.get(new SubsystemWrapper(parent));
+ if (children == null || children.isEmpty())
+ return Collections.emptySet();
+ Collection<Subsystem> result = new ArrayList<Subsystem>(children.size());
+ for (SubsystemWrapper child : children)
+ result.add(child.getSubsystem());
+ return Collections.unmodifiableCollection(result);
+ }
+
+ public synchronized Collection<Subsystem> getParents(Subsystem child) {
+ Collection<SubsystemWrapper> parents = getParents(new SubsystemWrapper(child));
+ Collection<Subsystem> result = new ArrayList<Subsystem>(parents.size());
+ for (SubsystemWrapper parent : parents) {
+ result.add(parent.getSubsystem());
+ }
+ return Collections.unmodifiableCollection(result);
+ }
+
+ public synchronized void remove(Subsystem subsystem) {
+ SubsystemWrapper subsystemWrap = new SubsystemWrapper(subsystem);
+ Collection<SubsystemWrapper> parents = getParents(subsystemWrap);
+ for (SubsystemWrapper parent : parents)
+ adjacencyList.get(parent).remove(subsystemWrap);
+ adjacencyList.remove(subsystemWrap);
+ }
+
+ private boolean containsAncestor(SubsystemWrapper subsystem, SubsystemWrapper ancestor) {
+ Collection<SubsystemWrapper> subsystems = adjacencyList.get(subsystem);
+ if (subsystems == null)
+ return false;
+ if (subsystems.contains(ancestor))
+ return true;
+ for (SubsystemWrapper s : subsystems) {
+ return containsAncestor(s, ancestor);
+ }
+ return false;
+ }
+
+ private Collection<SubsystemWrapper> getParents(SubsystemWrapper child) {
+ ArrayList<SubsystemWrapper> result = new ArrayList<SubsystemWrapper>();
+ for (Entry<SubsystemWrapper, Collection<SubsystemWrapper>> entry : adjacencyList.entrySet())
+ if (entry.getValue().contains(child))
+ result.add(entry.getKey());
+ result.trimToSize();
+ return result;
+ }
+}
Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemServiceRegistrar.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemServiceRegistrar.java?rev=1245802&r1=1245801&r2=1245802&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemServiceRegistrar.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemServiceRegistrar.java Fri Feb 17 23:17:51 2012
@@ -23,7 +23,7 @@ public class SubsystemServiceRegistrar {
public synchronized void register(Subsystem subsystem) {
if (map.containsKey(subsystem))
- throw new IllegalArgumentException("Subsystem '" + subsystem + "' already has service registration '" + map.get(subsystem) + "'");
+ throw new IllegalStateException("Subsystem '" + subsystem + "' already has service registration '" + map.get(subsystem) + "'");
Dictionary<String, Object> properties = properties(subsystem);
ServiceRegistration<Subsystem> registration = context.registerService(Subsystem.class, subsystem, properties);
map.put(subsystem, registration);