You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@oozie.apache.org by an...@apache.org on 2012/02/25 01:50:41 UTC

svn commit: r1293498 - in /incubator/oozie/trunk: ./ core/src/main/java/org/apache/oozie/ core/src/main/java/org/apache/oozie/workflow/lite/ core/src/test/java/org/apache/oozie/workflow/lite/

Author: angeloh
Date: Sat Feb 25 00:50:40 2012
New Revision: 1293498

URL: http://svn.apache.org/viewvc?rev=1293498&view=rev
Log:
OOZIE-693 Fork-join validation doesn't check for the 'error to' transition of nodes (Virag Kothari via Angelo)

Modified:
    incubator/oozie/trunk/core/src/main/java/org/apache/oozie/ErrorCode.java
    incubator/oozie/trunk/core/src/main/java/org/apache/oozie/workflow/lite/LiteWorkflowAppParser.java
    incubator/oozie/trunk/core/src/test/java/org/apache/oozie/workflow/lite/TestLiteWorkflowAppParser.java
    incubator/oozie/trunk/release-log.txt

Modified: incubator/oozie/trunk/core/src/main/java/org/apache/oozie/ErrorCode.java
URL: http://svn.apache.org/viewvc/incubator/oozie/trunk/core/src/main/java/org/apache/oozie/ErrorCode.java?rev=1293498&r1=1293497&r2=1293498&view=diff
==============================================================================
--- incubator/oozie/trunk/core/src/main/java/org/apache/oozie/ErrorCode.java (original)
+++ incubator/oozie/trunk/core/src/main/java/org/apache/oozie/ErrorCode.java Sat Feb 25 00:50:40 2012
@@ -138,6 +138,7 @@ public enum ErrorCode {
     E0732(XLog.STD, "Fork [{0}]/Join [{1}] not in pair"),
     E0733(XLog.STD, "Fork [{0}] without a join"),
     E0734(XLog.STD, "Invalid transition from node [{0}] to node [{1}] while using fork/join"),
+    E0735(XLog.STD, "There was an invalid \"error to\" transition to node [{1}] while using fork/join"),
 
     E0800(XLog.STD, "Action it is not running its in [{1}] state, action [{0}]"),
     E0801(XLog.STD, "Workflow already running, workflow [{0}]"),

Modified: incubator/oozie/trunk/core/src/main/java/org/apache/oozie/workflow/lite/LiteWorkflowAppParser.java
URL: http://svn.apache.org/viewvc/incubator/oozie/trunk/core/src/main/java/org/apache/oozie/workflow/lite/LiteWorkflowAppParser.java?rev=1293498&r1=1293497&r2=1293498&view=diff
==============================================================================
--- incubator/oozie/trunk/core/src/main/java/org/apache/oozie/workflow/lite/LiteWorkflowAppParser.java (original)
+++ incubator/oozie/trunk/core/src/main/java/org/apache/oozie/workflow/lite/LiteWorkflowAppParser.java Sat Feb 25 00:50:40 2012
@@ -164,6 +164,8 @@ public class LiteWorkflowAppParser {
      */
     private NodeDef validateFork(NodeDef forkNode, LiteWorkflowApp app) throws WorkflowException {
         List<String> transitions = new ArrayList<String>(forkNode.getTransitions());
+        // list for keeping track of "error-to" transitions of Action Node
+        List<String> errorToTransitions = new ArrayList<String>();
         String joinNode = null;
         for (int i = 0; i < transitions.size(); i++) {
             NodeDef node = app.getNode(transitions.get(i));
@@ -177,19 +179,23 @@ public class LiteWorkflowAppParser {
                     }
                 }
             } else if (node instanceof ActionNodeDef) {
-                // Get only the "ok-to" transition of node
-                String okToTransition = node.getTransitions().get(0);
                 // Make sure the transition is valid
-                validateTransition(transitions, app, okToTransition, node);
-                transitions.add(okToTransition);
+                validateTransition(errorToTransitions, transitions, app, node);
+                // Add the "ok-to" transition of node
+                transitions.add(node.getTransitions().get(0));
+                String errorTo = node.getTransitions().get(1);
+                // Add the "error-to" transition if the transition is a Action Node
+                if (app.getNode(errorTo) instanceof ActionNodeDef) {
+                    errorToTransitions.add(errorTo);
+                }
             } else if (node instanceof ForkNodeDef) {
                 forkList.remove(node.getName());
                 // Make a recursive call to resolve this fork node
                 NodeDef joinNd = validateFork(node, app);
-                String okToTransition = joinNd.getTransitions().get(0);
                 // Make sure the transition is valid
-                validateTransition(transitions, app, okToTransition, node);
-                transitions.add(okToTransition);
+                validateTransition(errorToTransitions, transitions, app, node);
+                // Add the "ok-to" transition of node
+                transitions.add(joinNd.getTransitions().get(0));
             } else if (node instanceof JoinNodeDef) {
                 // If joinNode encountered for the first time, remove it from the joinList and remember it
                 String currentJoin = node.getName();
@@ -213,12 +219,19 @@ public class LiteWorkflowAppParser {
 
     }
 
-    private void validateTransition(List<String> transitions, LiteWorkflowApp app, String okToTransition, NodeDef node)
+    private void validateTransition(List<String> errorToTransitions, List<String> transitions, LiteWorkflowApp app, NodeDef node)
             throws WorkflowException {
-        // Make sure the transition node is either a join node or is not already visited
-        if (transitions.contains(okToTransition) && !(app.getNode(okToTransition) instanceof JoinNodeDef)) {
-            throw new WorkflowException(ErrorCode.E0734, node.getName(), okToTransition);
+        for (String transition : node.getTransitions()) {
+            // Make sure the transition node is either a join node or is not already visited
+            if (transitions.contains(transition) && !(app.getNode(transition) instanceof JoinNodeDef)) {
+                throw new WorkflowException(ErrorCode.E0734, node.getName(), transition);
+            }
+            // Make sure the transition node is not the same as an already visited 'error-to' transition
+            if (errorToTransitions.contains(transition)) {
+                throw new WorkflowException(ErrorCode.E0735, node.getName(), transition);
+            }
         }
+
     }
 
     /**

Modified: incubator/oozie/trunk/core/src/test/java/org/apache/oozie/workflow/lite/TestLiteWorkflowAppParser.java
URL: http://svn.apache.org/viewvc/incubator/oozie/trunk/core/src/test/java/org/apache/oozie/workflow/lite/TestLiteWorkflowAppParser.java?rev=1293498&r1=1293497&r2=1293498&view=diff
==============================================================================
--- incubator/oozie/trunk/core/src/test/java/org/apache/oozie/workflow/lite/TestLiteWorkflowAppParser.java (original)
+++ incubator/oozie/trunk/core/src/test/java/org/apache/oozie/workflow/lite/TestLiteWorkflowAppParser.java Sat Feb 25 00:50:40 2012
@@ -121,7 +121,7 @@ public class TestLiteWorkflowAppParser e
             invokeForkJoin(parser, def);
         } catch (Exception e) {
             e.printStackTrace();
-            fail();
+            fail("Unexpected Exception");
         }
     }
 
@@ -147,7 +147,7 @@ public class TestLiteWorkflowAppParser e
             invokeForkJoin(parser, def);
         } catch (Exception e) {
             e.printStackTrace();
-            fail();
+            fail("Unexpected Exception");
         }
     }
 
@@ -183,7 +183,7 @@ public class TestLiteWorkflowAppParser e
             invokeForkJoin(parser, def);
         } catch (Exception e) {
             e.printStackTrace();
-            fail();
+            fail("Unexpected Exception");
         }
     }
 
@@ -207,7 +207,7 @@ public class TestLiteWorkflowAppParser e
 
         try {
             invokeForkJoin(parser, def);
-            fail();
+            fail("Expected to catch an exception but did not encounter any");
         } catch (Exception ex) {
             WorkflowException we = (WorkflowException) ex.getCause();
             assertEquals(ErrorCode.E0730, we.getErrorCode());
@@ -245,7 +245,7 @@ public class TestLiteWorkflowAppParser e
 
         try {
             invokeForkJoin(parser, def);
-            fail();
+            fail("Expected to catch an exception but did not encounter any");
         } catch (Exception ex) {
             WorkflowException we = (WorkflowException) ex.getCause();
             assertEquals(ErrorCode.E0730, we.getErrorCode());
@@ -259,7 +259,7 @@ public class TestLiteWorkflowAppParser e
      3->ok->j
      3->fail->end
     */
-    public void testTransitionFailure() throws WorkflowException{
+    public void testTransitionFailure1() throws WorkflowException{
         LiteWorkflowAppParser parser = new LiteWorkflowAppParser(null,
                 LiteWorkflowStoreService.LiteDecisionHandler.class,
                 LiteWorkflowStoreService.LiteActionHandler.class);
@@ -274,7 +274,7 @@ public class TestLiteWorkflowAppParser e
 
         try {
             invokeForkJoin(parser, def);
-            fail();
+            fail("Expected to catch an exception but did not encounter any");
         } catch (Exception ex) {
             WorkflowException we = (WorkflowException) ex.getCause();
             assertEquals(ErrorCode.E0734, we.getErrorCode());
@@ -287,6 +287,108 @@ public class TestLiteWorkflowAppParser e
 
     /*
     f->(2,3)
+    2->fail->3
+    2->ok->j
+    3->ok->j
+    3->fail->end
+   */
+   public void testTransitionFailure2() throws WorkflowException{
+       LiteWorkflowAppParser parser = new LiteWorkflowAppParser(null,
+               LiteWorkflowStoreService.LiteDecisionHandler.class,
+               LiteWorkflowStoreService.LiteActionHandler.class);
+
+       LiteWorkflowApp def = new LiteWorkflowApp("name", "def", new StartNodeDef("one"))
+       .addNode(new ActionNodeDef("one", dummyConf, TestActionNodeHandler.class, "f","end"))
+       .addNode(new ForkNodeDef("f", Arrays.asList(new String[]{"two","three"})))
+       .addNode(new ActionNodeDef("two", dummyConf, TestActionNodeHandler.class, "j", "three"))
+       .addNode(new ActionNodeDef("three", dummyConf, TestActionNodeHandler.class, "j", "end"))
+       .addNode(new JoinNodeDef("j", "end"))
+       .addNode(new EndNodeDef("end"));
+
+       try {
+           invokeForkJoin(parser, def);
+           fail("Expected to catch an exception but did not encounter any");
+       } catch (Exception ex) {
+           WorkflowException we = (WorkflowException) ex.getCause();
+           assertEquals(ErrorCode.E0734, we.getErrorCode());
+           // Make sure the message contains the nodes involved in the invalid transition
+           assertTrue(we.getMessage().contains("two"));
+           assertTrue(we.getMessage().contains("three"));
+       }
+
+   }
+
+   /*
+   f->(2,3)
+   2->ok->j
+   3->ok->4
+   2->fail->4
+   4->ok->j
+  */
+   public void testTransitionFailure3() throws WorkflowException{
+       LiteWorkflowAppParser parser = new LiteWorkflowAppParser(null,
+               LiteWorkflowStoreService.LiteDecisionHandler.class,
+               LiteWorkflowStoreService.LiteActionHandler.class);
+
+       LiteWorkflowApp def = new LiteWorkflowApp("name", "def", new StartNodeDef("one"))
+       .addNode(new ActionNodeDef("one", dummyConf, TestActionNodeHandler.class, "f","end"))
+       .addNode(new ForkNodeDef("f", Arrays.asList(new String[]{"two","three"})))
+       .addNode(new ActionNodeDef("two", dummyConf, TestActionNodeHandler.class, "j", "four"))
+       .addNode(new ActionNodeDef("three", dummyConf, TestActionNodeHandler.class, "four", "end"))
+       .addNode(new ActionNodeDef("four", dummyConf, TestActionNodeHandler.class, "j", "end"))
+       .addNode(new JoinNodeDef("j", "end"))
+       .addNode(new EndNodeDef("end"));
+
+       try {
+           invokeForkJoin(parser, def);
+           fail("Expected to catch an exception but did not encounter any");
+       } catch (Exception ex) {
+           WorkflowException we = (WorkflowException) ex.getCause();
+           assertEquals(ErrorCode.E0735, we.getErrorCode());
+           // Make sure the message contains the node involved in the invalid transition
+           assertTrue(we.getMessage().contains("four"));
+       }
+   }
+
+   /*
+    * f->(2,3)
+    * 2->ok->j
+    * 3->ok->j
+    * j->end
+    * 2->error->f1
+    * 3->error->f1
+    * f1->(4,5)
+    * (4,5)->j1
+    * j1->end
+    */
+   public void testErrorTransitionForkJoin() throws WorkflowException {
+       LiteWorkflowAppParser parser = new LiteWorkflowAppParser(null,
+               LiteWorkflowStoreService.LiteDecisionHandler.class,
+               LiteWorkflowStoreService.LiteActionHandler.class);
+
+       LiteWorkflowApp def = new LiteWorkflowApp("wf", "<worklfow-app/>", new StartNodeDef("one"))
+       .addNode(new ActionNodeDef("one", dummyConf, TestActionNodeHandler.class, "f", "end"))
+       .addNode(new ForkNodeDef("f", Arrays.asList(new String[]{"two", "three"})))
+       .addNode(new ActionNodeDef("two", dummyConf,  TestActionNodeHandler.class, "j", "f1"))
+       .addNode(new ActionNodeDef("three", dummyConf, TestActionNodeHandler.class, "j", "f1"))
+       .addNode(new ForkNodeDef("f1", Arrays.asList(new String[]{"four", "five"})))
+       .addNode(new ActionNodeDef("four", dummyConf,  TestActionNodeHandler.class, "j1", "end"))
+       .addNode(new ActionNodeDef("five", dummyConf, TestActionNodeHandler.class, "j1", "end"))
+       .addNode(new JoinNodeDef("j", "six"))
+       .addNode(new JoinNodeDef("j1", "six"))
+       .addNode(new ActionNodeDef("six", dummyConf, TestActionNodeHandler.class, "end", "end"))
+       .addNode(new EndNodeDef("end"));
+
+       try {
+           invokeForkJoin(parser, def);
+       } catch (Exception e) {
+           e.printStackTrace();
+           fail("Unexpected Exception");
+       }
+   }
+
+    /*
+    f->(2,3)
     2->decision node->{4,5,4}
     4->j
     5->j
@@ -310,7 +412,7 @@ public class TestLiteWorkflowAppParser e
             invokeForkJoin(parser, def);
         } catch (Exception e) {
             e.printStackTrace();
-            fail();
+            fail("Unexpected Exception");
         }
     }
 
@@ -335,7 +437,7 @@ public class TestLiteWorkflowAppParser e
 
         try {
             invokeForkJoin(parser, def);
-            fail();
+            fail("Expected to catch an exception but did not encounter any");
         } catch (Exception ex) {
             WorkflowException we = (WorkflowException) ex.getCause();
             assertEquals(ErrorCode.E0734, we.getErrorCode());
@@ -374,14 +476,14 @@ public class TestLiteWorkflowAppParser e
             invokeForkJoin(parser, def);
         } catch (Exception e) {
             e.printStackTrace();
-            fail();
+            fail("Unexpected Exception");
         }
     }
 
     // Invoke private validateForkJoin method using Reflection API
     private void invokeForkJoin(LiteWorkflowAppParser parser, LiteWorkflowApp def) throws Exception {
         Class<? extends LiteWorkflowAppParser> c = parser.getClass();
-        Class d = Class.forName("org.apache.oozie.workflow.lite.LiteWorkflowAppParser$VisitStatus");
+        Class<?> d = Class.forName("org.apache.oozie.workflow.lite.LiteWorkflowAppParser$VisitStatus");
         Field f = d.getField("VISITING");
         Map traversed = new HashMap();
         traversed.put(def.getNode(StartNodeDef.START).getName(), f);

Modified: incubator/oozie/trunk/release-log.txt
URL: http://svn.apache.org/viewvc/incubator/oozie/trunk/release-log.txt?rev=1293498&r1=1293497&r2=1293498&view=diff
==============================================================================
--- incubator/oozie/trunk/release-log.txt (original)
+++ incubator/oozie/trunk/release-log.txt Sat Feb 25 00:50:40 2012
@@ -1,5 +1,6 @@
 -- Oozie 3.2.0 release
 
+OOZIE-693 Fork-join validation doesn't check for the 'error to' transition of nodes (Virag Kothari via Angelo)
 OOZIE-616 Moving action prepare FS execution to LauncherMapper ( Kiran Nagasubramanian via Angelo)
 OOZIE-687 The start time of the action is set after the job is already submitted to hadoop (Mohamed Battisha vis Angelo)
 OOZIE-712 Hive testcases fail with 0.23 (tucu)