[jboss-cvs] JBossAS SVN: r99112 - in projects/jboss-deployers/trunk/deployers-impl/src: test/java/org/jboss/test/deployers/deployer/test and 1 other directory.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Thu Jan 7 07:58:21 EST 2010


Author: richard.opalka at jboss.com
Date: 2010-01-07 07:58:21 -0500 (Thu, 07 Jan 2010)
New Revision: 99112

Added:
   projects/jboss-deployers/trunk/deployers-impl/src/main/java/org/jboss/deployers/plugins/sort/TopologicalOrderingDeployerSorter.java
   projects/jboss-deployers/trunk/deployers-impl/src/test/java/org/jboss/test/deployers/deployer/test/OptimizedTopologicalOrderingUnitTestCase.java
Modified:
   projects/jboss-deployers/trunk/deployers-impl/src/main/java/org/jboss/deployers/plugins/sort/DeployerSorterFactory.java
   projects/jboss-deployers/trunk/deployers-impl/src/test/java/org/jboss/test/deployers/deployer/test/AbstractDeployerFlowUnitTest.java
   projects/jboss-deployers/trunk/deployers-impl/src/test/java/org/jboss/test/deployers/deployer/test/DominoOrderingUnitTestCase.java
   projects/jboss-deployers/trunk/deployers-impl/src/test/java/org/jboss/test/deployers/deployer/test/KahnOrderingUnitTestCase.java
   projects/jboss-deployers/trunk/deployers-impl/src/test/java/org/jboss/test/deployers/deployer/test/TopologicalOrderingUnitTestCase.java
Log:
[JBDEPLOY-229][JBDEPLOY-230] fixing issue

Modified: projects/jboss-deployers/trunk/deployers-impl/src/main/java/org/jboss/deployers/plugins/sort/DeployerSorterFactory.java
===================================================================
--- projects/jboss-deployers/trunk/deployers-impl/src/main/java/org/jboss/deployers/plugins/sort/DeployerSorterFactory.java	2010-01-07 12:46:43 UTC (rev 99111)
+++ projects/jboss-deployers/trunk/deployers-impl/src/main/java/org/jboss/deployers/plugins/sort/DeployerSorterFactory.java	2010-01-07 12:58:21 UTC (rev 99112)
@@ -25,6 +25,7 @@
  * Sorter factory.
  *
  * @author <a href="mailto:ales.justin at jboss.com">Ales Justin</a>
+ * @author <a href="mailto:ropalka at redhat.com">Richard Opalka</a>
  */
 public class DeployerSorterFactory
 {
@@ -36,6 +37,6 @@
     */
    public static DeployerSorter newSorter()
    {
-      return new KahnDeployerSorter();      
+      return new TopologicalOrderingDeployerSorter();      
    }
 }

Added: projects/jboss-deployers/trunk/deployers-impl/src/main/java/org/jboss/deployers/plugins/sort/TopologicalOrderingDeployerSorter.java
===================================================================
--- projects/jboss-deployers/trunk/deployers-impl/src/main/java/org/jboss/deployers/plugins/sort/TopologicalOrderingDeployerSorter.java	                        (rev 0)
+++ projects/jboss-deployers/trunk/deployers-impl/src/main/java/org/jboss/deployers/plugins/sort/TopologicalOrderingDeployerSorter.java	2010-01-07 12:58:21 UTC (rev 99112)
@@ -0,0 +1,317 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright (c) 2010, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.deployers.plugins.sort;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.jboss.deployers.spi.Ordered;
+import org.jboss.deployers.spi.deployer.Deployer;
+
+/**
+ * Implements <a href="http://en.wikipedia.org/wiki/Topological_sorting">topological sorting</a> for acyclic graphs.
+ * The algorithm complexity is O(m+n), where <b>m</b> = count of vertices and <b>n</b> = count of edges in general.
+ * However this complexity isn't true for this algorithm implementation, because there's backward compatibility
+ * requirement that deployers have to be ordered by their relative number or name if they're on the same processing level.
+ * <b>IOW this backward compatible sorting requirement breaks linear algorithm complexity :(</b>.
+ *
+ * @author <a href="mailto:ropalka at redhat.com">Richard Opalka</a>
+ */
+public class TopologicalOrderingDeployerSorter implements DeployerSorter
+{
+
+   /**
+    * @see {@link DeployerSorter#sortDeployers(List, Deployer)}
+    */
+   public List<Deployer> sortDeployers(List<Deployer> registeredDeployers, Deployer newDeployer)
+   {
+      return this.createOrientedGraph(registeredDeployers, newDeployer).sort();
+   }
+
+   private Graph createOrientedGraph(final List<Deployer> deployers, final Deployer newDeployer)
+   {
+      final Graph graph = new Graph();
+
+      for (final Deployer deployer : deployers)
+         graph.addVertex(deployer);
+
+      graph.addVertex(newDeployer);
+      graph.createEdges();
+
+      return graph;
+   }
+
+
+   private static class Graph
+   {
+      private Map<String, Dependency> dependencies = new HashMap<String, Dependency>();
+      private Set<Vertex> vertices = new HashSet<Vertex>();
+
+      public void addVertex(final Deployer deployer)
+      {
+         // create disjunct sets
+         final Set<String> inputs = new HashSet<String>();
+         inputs.addAll(deployer.getInputs());
+         final Set<String> outputs = new HashSet<String>();
+         outputs.addAll(deployer.getOutputs());
+         final Set<String> intersection = this.getIntersection(inputs, outputs);
+
+         // register vertex
+         final Vertex vertex = new Vertex(deployer);
+         this.vertices.add(vertex);
+
+         // register dependencies
+         Dependency dependency = null;
+         for (final String in : inputs)
+         {
+            dependency = this.getDependency(in);
+            dependency.consumers.add(vertex);
+         }
+
+         for (final String inOut : intersection)
+         {
+            dependency = this.getDependency(inOut);
+            dependency.modifiers.add(vertex);
+         }
+
+         for (final String out : outputs)
+         {
+            dependency = this.getDependency(out);
+            dependency.producers.add(vertex);
+         }
+      }
+
+      public List<Deployer> sort()
+      {
+         // L ← Empty list that will contain the sorted elements
+         List<Deployer> retVal = new LinkedList<Deployer>();
+         // S ← Set of all nodes with no incoming edges
+         List<Vertex> roots = this.getRoots();
+         // ensure backward compatibility
+         Collections.sort(roots, Ordered.COMPARATOR);
+
+         // while S is non-empty do
+         Vertex root = null;
+         Set<Vertex> nextLevel = null;
+         while(!roots.isEmpty())
+         {
+            // remove a node n from S
+            root = roots.remove(0);
+            // insert n into L
+            retVal.add(root.getDeployer());
+
+            // for each node m with an edge e from n to m do
+            if (root.hasConsumers())
+            {
+               // ensure backward compatibility
+               nextLevel = new TreeSet<Vertex>(Ordered.COMPARATOR);
+               for(final Vertex consumer : root.consumers)
+               {
+                  // remove edge e from the graph
+                  consumer.decrementDegree();
+                  // if m has no other incoming edges then insert m into S
+                  if (!consumer.hasProducers())
+                  {
+                     this.remove(consumer);
+                     nextLevel.add(consumer);
+                  }
+               }
+
+               // append to the end of list in sorted order
+               roots.addAll(nextLevel);
+            }
+         }
+
+         if (this.vertices.size() > 0)
+         {
+            // if graph has edges then graph has at least one cycle
+            throw new IllegalStateException("Cycle detected");
+         }
+         else
+         {
+            // topologically sorted order
+            return retVal;
+         }
+      }
+
+      private Set<String> getIntersection(final Set<String> inputs, final Set<String> outputs)
+      {
+         final Set<String> intersection = new HashSet<String>();
+
+         for (final String input : inputs)
+            for (final String output : outputs)
+               if (input.equals(output)) 
+                  intersection.add(input);
+
+         inputs.removeAll(intersection);
+         outputs.removeAll(intersection);
+
+         return intersection;
+      }
+
+      private Dependency getDependency(final String name)
+      {
+         if (this.dependencies.containsKey(name))
+         {
+            return this.dependencies.get(name);
+         }
+         else
+         {
+            final Dependency newDependency = new Dependency();
+            this.dependencies.put(name, newDependency);
+            return newDependency;
+         }
+      }
+
+      private void createEdges()
+      {
+         boolean hasModifiers = false;
+         Dependency dependency = null;
+
+         for (final String dependencyName : this.dependencies.keySet())
+         {
+            dependency = this.dependencies.get(dependencyName);
+            hasModifiers = dependency.modifiers.size() > 0;
+
+            if (hasModifiers)
+            {
+               this.createEdges(dependency.producers, dependency.modifiers);
+               this.createEdges(dependency.modifiers, dependency.consumers);
+            }
+            else
+            {
+               this.createEdges(dependency.producers, dependency.consumers);
+            }
+         }
+      }
+
+      private void createEdges(final List<Vertex> producers, final List<Vertex> consumers)
+      {
+         for (final Vertex producer : producers)
+            for (final Vertex consumer : consumers)
+            {
+               producer.addConsumer(consumer);
+               consumer.incrementDegree();
+            }
+      }
+
+      private List<Vertex> getRoots()
+      {
+         final LinkedList<Vertex> retVal = new LinkedList<Vertex>();
+
+         for (final Vertex current : this.vertices)
+            if (!current.hasProducers())
+               retVal.add(current);
+
+         for (final Vertex root : retVal)
+            this.remove(root);
+
+         return retVal;
+      }
+
+      private void remove(final Vertex v)
+      {
+         this.vertices.remove(v);
+      }
+
+      private static class Vertex implements Ordered
+      {
+         // Wrapped deployer
+         private Deployer deployer;
+         // Incoming edges
+         private int inDegree = 0;
+         // Outgoing edges
+         private List<Vertex> consumers = new LinkedList<Vertex>();
+
+         public Vertex(final Deployer deployer)
+         {
+            if (deployer == null)
+               throw new IllegalArgumentException();
+
+            this.deployer = deployer;
+         }
+
+         public void incrementDegree()
+         {
+            this.inDegree++;
+         }
+
+         public void decrementDegree()
+         {
+            this.inDegree--;
+         }
+
+         public void addConsumer(final Vertex v)
+         {
+            this.consumers.add(v);
+         }
+
+         public boolean hasProducers()
+         {
+            return this.inDegree > 0;
+         }
+
+         public boolean hasConsumers()
+         {
+            return this.consumers.size() > 0;
+         }
+
+         public Deployer getDeployer()
+         {
+            return this.deployer;
+         }
+
+         public int getRelativeOrder()
+         {
+            return this.deployer.getRelativeOrder();
+         }
+
+         public void setRelativeOrder(final int order)
+         {
+            throw new UnsupportedOperationException();
+         }
+
+         public String toString()
+         {
+            return this.deployer.toString();
+         }
+      }
+
+      private static class Dependency
+      {
+         // deployers creating this dependency
+         private List<Vertex> producers = new LinkedList<Vertex>();
+         // deployers modifying this dependency
+         private List<Vertex> modifiers = new LinkedList<Vertex>();
+         // deployers consuming this dependency
+         private List<Vertex> consumers= new LinkedList<Vertex>();
+      }
+
+   }
+
+}

Modified: projects/jboss-deployers/trunk/deployers-impl/src/test/java/org/jboss/test/deployers/deployer/test/AbstractDeployerFlowUnitTest.java
===================================================================
--- projects/jboss-deployers/trunk/deployers-impl/src/test/java/org/jboss/test/deployers/deployer/test/AbstractDeployerFlowUnitTest.java	2010-01-07 12:46:43 UTC (rev 99111)
+++ projects/jboss-deployers/trunk/deployers-impl/src/test/java/org/jboss/test/deployers/deployer/test/AbstractDeployerFlowUnitTest.java	2010-01-07 12:58:21 UTC (rev 99112)
@@ -21,6 +21,9 @@
  */
 package org.jboss.test.deployers.deployer.test;
 
+import java.util.LinkedList;
+import java.util.List;
+
 import org.jboss.deployers.client.spi.DeployerClient;
 import org.jboss.deployers.client.spi.Deployment;
 import org.jboss.deployers.plugins.deployers.DeployersImpl;
@@ -1233,7 +1236,36 @@
       main.removeDeployment(deployment);
       main.process();
    }
+   
+   public void testAlgorithmPerformance() throws Exception
+   {
+      DeployerClient main = createMainDeployer();
+      AbstractDeployer deployer;
+      final int COUNT_OF_DEPLOYERS = 500;
 
+      List<AbstractDeployer> deployers = new LinkedList<AbstractDeployer>();
+
+      for (int i = 0; i < COUNT_OF_DEPLOYERS; i++)
+      {
+         deployer = new TestDeployerAdapter( String.valueOf(i) );
+         deployer.setOutputs( String.valueOf(i) );
+         for (int j = 0; j < i; j++) deployer.addInput( String.valueOf(j) );
+         deployer.setStage(DeploymentStages.REAL);
+         deployers.add(deployer);
+      }
+      
+      long start = System.currentTimeMillis();
+      for (AbstractDeployer d : deployers)
+      {
+         addDeployer(main, d);
+      }
+      long end = System.currentTimeMillis();
+      
+      System.out.println("------------------------------------------------------------------------");
+      System.out.println("Exhaustive deployer sorting (" + getClass().getSimpleName() +  ") took: " + (end - start) + " milliseconds");
+      System.out.println("------------------------------------------------------------------------");
+   }
+
    public void testRealWorldAS6DeployersScenario() throws Exception
    {
       // THIS IS REAL WORLD SCENARIO - AS deployers with their dependencies

Modified: projects/jboss-deployers/trunk/deployers-impl/src/test/java/org/jboss/test/deployers/deployer/test/DominoOrderingUnitTestCase.java
===================================================================
--- projects/jboss-deployers/trunk/deployers-impl/src/test/java/org/jboss/test/deployers/deployer/test/DominoOrderingUnitTestCase.java	2010-01-07 12:46:43 UTC (rev 99111)
+++ projects/jboss-deployers/trunk/deployers-impl/src/test/java/org/jboss/test/deployers/deployer/test/DominoOrderingUnitTestCase.java	2010-01-07 12:58:21 UTC (rev 99112)
@@ -49,4 +49,11 @@
    {
       return new DominoDeployerSorter();
    }
+   
+   public void testAlgorithmPerformance()
+   {
+      System.out.println("------------------------------------------------------------------------");
+      System.out.println("Exhaustive deployer sorting (" + getClass().getSimpleName() +  ") took: NOT MEASURED (too slow)");
+      System.out.println("------------------------------------------------------------------------");
+   }
 }
\ No newline at end of file

Modified: projects/jboss-deployers/trunk/deployers-impl/src/test/java/org/jboss/test/deployers/deployer/test/KahnOrderingUnitTestCase.java
===================================================================
--- projects/jboss-deployers/trunk/deployers-impl/src/test/java/org/jboss/test/deployers/deployer/test/KahnOrderingUnitTestCase.java	2010-01-07 12:46:43 UTC (rev 99111)
+++ projects/jboss-deployers/trunk/deployers-impl/src/test/java/org/jboss/test/deployers/deployer/test/KahnOrderingUnitTestCase.java	2010-01-07 12:58:21 UTC (rev 99112)
@@ -49,4 +49,11 @@
    {
       return new KahnDeployerSorter();
    }
+   
+   public void testAlgorithmPerformance()
+   {
+      System.out.println("------------------------------------------------------------------------");
+      System.out.println("Exhaustive deployer sorting (" + getClass().getSimpleName() +  ") took: NOT MEASURED (too slow)");
+      System.out.println("------------------------------------------------------------------------");
+   }
 }
\ No newline at end of file

Added: projects/jboss-deployers/trunk/deployers-impl/src/test/java/org/jboss/test/deployers/deployer/test/OptimizedTopologicalOrderingUnitTestCase.java
===================================================================
--- projects/jboss-deployers/trunk/deployers-impl/src/test/java/org/jboss/test/deployers/deployer/test/OptimizedTopologicalOrderingUnitTestCase.java	                        (rev 0)
+++ projects/jboss-deployers/trunk/deployers-impl/src/test/java/org/jboss/test/deployers/deployer/test/OptimizedTopologicalOrderingUnitTestCase.java	2010-01-07 12:58:21 UTC (rev 99112)
@@ -0,0 +1,52 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright (c) 2010, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.test.deployers.deployer.test;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.jboss.deployers.plugins.sort.DeployerSorter;
+import org.jboss.deployers.plugins.sort.TopologicalOrderingDeployerSorter;
+
+/**
+ * Tests topological sorting.
+ *
+ * @author <a href="mailto:ropalka at redhat.com">Richard Opalka</a>
+ */
+public class OptimizedTopologicalOrderingUnitTestCase extends AbstractSorterOrderingUnitTest
+{
+   public OptimizedTopologicalOrderingUnitTestCase(String name)
+   {
+      super(name);
+   }
+
+   public static Test suite()
+   {
+      return new TestSuite(OptimizedTopologicalOrderingUnitTestCase.class);
+   }
+
+   @Override
+   protected DeployerSorter createSorter()
+   {
+      return new TopologicalOrderingDeployerSorter();
+   }
+}

Modified: projects/jboss-deployers/trunk/deployers-impl/src/test/java/org/jboss/test/deployers/deployer/test/TopologicalOrderingUnitTestCase.java
===================================================================
--- projects/jboss-deployers/trunk/deployers-impl/src/test/java/org/jboss/test/deployers/deployer/test/TopologicalOrderingUnitTestCase.java	2010-01-07 12:46:43 UTC (rev 99111)
+++ projects/jboss-deployers/trunk/deployers-impl/src/test/java/org/jboss/test/deployers/deployer/test/TopologicalOrderingUnitTestCase.java	2010-01-07 12:58:21 UTC (rev 99112)
@@ -55,4 +55,11 @@
    {
       // TODO - how much do we allow pass-through to participate in ordering?
    }
+
+   public void testAlgorithmPerformance()
+   {
+      System.out.println("------------------------------------------------------------------------");
+      System.out.println("Exhaustive deployer sorting (" + getClass().getSimpleName() +  ") took: NOT MEASURED (too slow)");
+      System.out.println("------------------------------------------------------------------------");
+   }
 }
\ No newline at end of file




More information about the jboss-cvs-commits mailing list