Author: jwross
Date: Tue Apr 16 16:30:06 2013
New Revision: 1468495

URL: http://svn.apache.org/r1468495
Log:
Fix stale state written to deployment manifest.

There was a small window where a previous state could be written to a 
deployment manifest due
to holding a stale copy of the deployment manifest. This included *ING states 
so that subsequent
operations would end up waiting for a state change the would never occur.

Modified:
    
aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/AbstractAction.java
    
aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BasicSubsystem.java
    
aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/StopAction.java

Modified: 
aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/AbstractAction.java
URL: 
http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/AbstractAction.java?rev=1468495&r1=1468494&r2=1468495&view=diff
==============================================================================
--- 
aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/AbstractAction.java
 (original)
+++ 
aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/AbstractAction.java
 Tue Apr 16 16:30:06 2013
@@ -17,8 +17,12 @@ import java.security.PrivilegedAction;
 
 import org.osgi.service.subsystem.Subsystem.State;
 import org.osgi.service.subsystem.SubsystemException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public abstract class AbstractAction implements PrivilegedAction<Object> {
+       private static final Logger logger = 
LoggerFactory.getLogger(AbstractAction.class);
+       
        protected final boolean disableRootCheck;
        protected final BasicSubsystem requestor;
        protected final BasicSubsystem target;
@@ -43,13 +47,19 @@ public abstract class AbstractAction imp
        protected void waitForStateChange(State fromState) {
                long then = System.currentTimeMillis() + 60000;
                synchronized (target) {
+                       if (logger.isDebugEnabled())
+                               logger.debug("Request to wait for state change 
of subsystem {} from state {}", target.getSymbolicName(), target.getState());
                        while (target.getState().equals(fromState)) {
+                               if (logger.isDebugEnabled())
+                                       logger.debug("{} equals {}", 
target.getState(), fromState);
                                // State change has not occurred.
                                long now = System.currentTimeMillis();
                                if (then <= now)
                                        // Wait time has expired.
                                        throw new SubsystemException("Operation 
timed out while waiting for the subsystem to change state from " + fromState);
                                try {
+                                       if (logger.isDebugEnabled())
+                                               logger.debug("Waiting for {} 
ms", then - now);
                                        // Wait will never be called with zero 
or a negative
                                        // argument due to previous check.
                                        target.wait(then - now);
@@ -60,6 +70,8 @@ public abstract class AbstractAction imp
                                        throw new SubsystemException(e);
                                }
                        }
+                       if (logger.isDebugEnabled())
+                               logger.debug("Done waiting for subsystem {} in 
state {} to change from state {}", new Object[]{target.getSymbolicName(), 
target.getState(), fromState});
                }
        }
 }

Modified: 
aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BasicSubsystem.java
URL: 
http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BasicSubsystem.java?rev=1468495&r1=1468494&r2=1468495&view=diff
==============================================================================
--- 
aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BasicSubsystem.java
 (original)
+++ 
aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BasicSubsystem.java
 Tue Apr 16 16:30:06 2013
@@ -57,8 +57,12 @@ import org.osgi.service.resolver.Resolut
 import org.osgi.service.subsystem.Subsystem;
 import org.osgi.service.subsystem.SubsystemConstants;
 import org.osgi.service.subsystem.SubsystemException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class BasicSubsystem implements Resource, AriesSubsystem {
+       private static final Logger logger = 
LoggerFactory.getLogger(BasicSubsystem.class);
+       
        public static final String ROOT_SYMBOLIC_NAME = 
"org.osgi.service.subsystem.root";
        public static final Version ROOT_VERSION = 
Version.parseVersion("1.0.0");
        public static final String ROOT_LOCATION = "subsystem://?"
@@ -310,8 +314,14 @@ public class BasicSubsystem implements R
        
        void addedConstituent(Resource resource, boolean referenced) {
                try {
-                       setDeploymentManifest(new DeploymentManifest.Builder()
-                                       
.manifest(getDeploymentManifest()).content(resource, referenced).build());
+                       if (logger.isDebugEnabled())
+                               logger.debug("Adding constituent {} to 
deployment manifest...", resource);
+                       synchronized (this) {
+                               setDeploymentManifest(new 
DeploymentManifest.Builder()
+                                               
.manifest(getDeploymentManifest()).content(resource, referenced).build());
+                       }
+                       if (logger.isDebugEnabled())
+                               logger.debug("Added constituent {} to 
deployment manifest", resource);
                } catch (Exception e) {
                        throw new SubsystemException(e);
                }
@@ -319,8 +329,14 @@ public class BasicSubsystem implements R
        
        void addedParent(BasicSubsystem subsystem, boolean referenceCount) {
                try {
-                       setDeploymentManifest(new DeploymentManifest.Builder()
-                                       
.manifest(getDeploymentManifest()).parent(subsystem, referenceCount).build());
+                       if (logger.isDebugEnabled())
+                               logger.debug("Adding parent {} to deployment 
manifest...", subsystem.getSymbolicName());
+                       synchronized (this) {
+                               setDeploymentManifest(new 
DeploymentManifest.Builder()
+                                               
.manifest(getDeploymentManifest()).parent(subsystem, referenceCount).build());
+                       }
+                       if (logger.isDebugEnabled())
+                               logger.debug("Added parent {} to deployment 
manifest", subsystem.getSymbolicName());
                } catch (Exception e) {
                        throw new SubsystemException(e);
                }
@@ -453,7 +469,7 @@ public class BasicSubsystem implements R
                removedContent(Collections.singleton(clause));
        }
        
-       void removedContent(Collection<DeployedContentHeader.Clause> content) {
+       synchronized void 
removedContent(Collection<DeployedContentHeader.Clause> content) {
                DeploymentManifest manifest = getDeploymentManifest();
                DeployedContentHeader header = 
manifest.getDeployedContentHeader();
                if (header == null)
@@ -481,8 +497,10 @@ public class BasicSubsystem implements R
        
        void setAutostart(boolean value) {
                try {
-                       setDeploymentManifest(new DeploymentManifest.Builder()
-                                       
.manifest(getDeploymentManifest()).autostart(value).build());
+                       synchronized (this) {
+                               setDeploymentManifest(new 
DeploymentManifest.Builder()
+                                               
.manifest(getDeploymentManifest()).autostart(value).build());
+                       }
                } catch (Exception e) {
                        throw new SubsystemException(e);
                }
@@ -491,6 +509,8 @@ public class BasicSubsystem implements R
        synchronized void setDeploymentManifest(DeploymentManifest value) 
throws IOException {
                deploymentManifest = value;
                Coordination coordination = 
Activator.getInstance().getCoordinator().peek();
+               if (logger.isDebugEnabled())
+                       logger.debug("Setting deployment manifest for subsystem 
{} using coordination {}", getSymbolicName(), coordination == null ? null : 
coordination.getName());
                if (coordination == null) {
                        saveDeploymentManifest();
                } else {
@@ -517,7 +537,11 @@ public class BasicSubsystem implements R
                        file.mkdirs();
                BufferedOutputStream out = new BufferedOutputStream(new 
FileOutputStream(new File(file, "DEPLOYMENT.MF")));
                try {
+                       if (logger.isDebugEnabled())
+                               logger.debug("Writing deployment manifest for 
subsystem {} in state {}", getSymbolicName(), getState());
                        deploymentManifest.write(out);
+                       if (logger.isDebugEnabled())
+                               logger.debug("Wrote deployment manifest for 
subsystem {} in state {}", getSymbolicName(), getState());
                }
                finally {
                        IOUtils.close(out);
@@ -525,16 +549,28 @@ public class BasicSubsystem implements R
        }
        
        void setState(State value) {
-               if (value.equals(getState()))
+               if (logger.isDebugEnabled())
+                       logger.debug("Setting state of subsystem {} to {}", 
getSymbolicName(), value);
+               State state = getState();
+               if (value.equals(state)) {
+                       if (logger.isDebugEnabled())
+                               logger.debug("Requested state {} equals current 
state {}", value, state);
                        return;
+               }
                try {
-                       setDeploymentManifest(new DeploymentManifest.Builder()
-                                       
.manifest(getDeploymentManifest()).state(value).build());
+                       if (logger.isDebugEnabled())
+                               logger.debug("Setting the deployment 
manifest...");
+                       synchronized (this) {
+                               setDeploymentManifest(new 
DeploymentManifest.Builder()
+                                               
.manifest(getDeploymentManifest()).state(value).build());
+                       }
                } catch (Exception e) {
                        throw new SubsystemException(e);
                }
                
Activator.getInstance().getSubsystemServiceRegistrar().update(this);
                synchronized (this) {
+                       if (logger.isDebugEnabled())
+                               logger.debug("Notifying all waiting for state 
change of subsystem {}", getSymbolicName());
                        notifyAll();
                }
        }
@@ -590,6 +626,8 @@ public class BasicSubsystem implements R
 
                @Override
                public void ended(Coordination coordination) throws Exception {
+                       if (logger.isDebugEnabled())
+                               logger.debug("Saving deployment manifests 
because coordination {} ended", coordination.getName());
                        Map<Class<?>, Object> variables = 
coordination.getVariables();
                        Set<BasicSubsystem> dirtySubsystems;
                        synchronized (variables) {
@@ -598,6 +636,8 @@ public class BasicSubsystem implements R
                                dirtySubsystems = temp == null ? Collections. 
<BasicSubsystem>emptySet() : temp;
                        }
                        for (BasicSubsystem dirtySubsystem : dirtySubsystems) {
+                               if (logger.isDebugEnabled())
+                                       logger.debug("Saving deployment 
manifest of subsystem {} for coordination {}", 
dirtySubsystem.getSymbolicName(), coordination.getName());
                                dirtySubsystem.saveDeploymentManifest();
                        }
                }

Modified: 
aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/StopAction.java
URL: 
http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/StopAction.java?rev=1468495&r1=1468494&r2=1468495&view=diff
==============================================================================
--- 
aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/StopAction.java
 (original)
+++ 
aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/StopAction.java
 Tue Apr 16 16:30:06 2013
@@ -71,15 +71,17 @@ public class StopAction extends Abstract
                // TODO Can we automatically assume it actually is resolved?
                target.setState(State.RESOLVED);
                try {
-                       target.setDeploymentManifest(new DeploymentManifest(
-                                       target.getDeploymentManifest(),
-                                       null,
-                                       target.isAutostart(),
-                                       target.getSubsystemId(),
-                                       SubsystemIdentifier.getLastId(),
-                                       target.getLocation(),
-                                       false,
-                                       false));
+                       synchronized (target) {
+                               target.setDeploymentManifest(new 
DeploymentManifest(
+                                               target.getDeploymentManifest(),
+                                               null,
+                                               target.isAutostart(),
+                                               target.getSubsystemId(),
+                                               SubsystemIdentifier.getLastId(),
+                                               target.getLocation(),
+                                               false,
+                                               false));
+                       }
                }
                catch (Exception e) {
                        throw new SubsystemException(e);


Reply via email to