| Index: core/src/test/java/org/apache/oozie/test/XTestCase.java |
| =================================================================== |
| --- core/src/test/java/org/apache/oozie/test/XTestCase.java (revision 1485571) |
| +++ core/src/test/java/org/apache/oozie/test/XTestCase.java (working copy) |
| @@ -75,7 +75,7 @@ |
| * From within testcases, system properties must be changed using the {@link #setSystemProperty} method. |
| */ |
| public abstract class XTestCase extends TestCase { |
| - private Map<String, String> sysProps; |
| + protected Map<String, String> sysProps; |
| private String testCaseDir; |
| private String testCaseConfDir; |
| private String hadoopVersion; |
| Index: core/src/test/java/org/apache/oozie/test/XDataTestCase.java |
| =================================================================== |
| --- core/src/test/java/org/apache/oozie/test/XDataTestCase.java (revision 1485571) |
| +++ core/src/test/java/org/apache/oozie/test/XDataTestCase.java (working copy) |
| @@ -121,6 +121,25 @@ |
| } |
| |
| /** |
| + * Inserts the passed coord job |
| + * @param coord job bean |
| + * @throws Exception |
| + */ |
| + protected void addRecordToCoordJobTable(CoordinatorJobBean coordJob) throws Exception { |
| + try { |
| + JPAService jpaService = Services.get().get(JPAService.class); |
| + assertNotNull(jpaService); |
| + CoordJobInsertJPAExecutor coordInsertCmd = new CoordJobInsertJPAExecutor(coordJob); |
| + jpaService.execute(coordInsertCmd); |
| + } |
| + catch (JPAExecutorException je) { |
| + je.printStackTrace(); |
| + fail("Unable to insert the test coord job record to table"); |
| + throw je; |
| + } |
| + } |
| + |
| + /** |
| * Insert coord job for testing. |
| * |
| * @param status coord job status |
| Index: core/src/test/java/org/apache/oozie/command/coord/CoordELExtensions.java |
| =================================================================== |
| --- core/src/test/java/org/apache/oozie/command/coord/CoordELExtensions.java (revision 0) |
| +++ core/src/test/java/org/apache/oozie/command/coord/CoordELExtensions.java (revision 0) |
| @@ -0,0 +1,77 @@ |
| +/** |
| + * Licensed to the Apache Software Foundation (ASF) under one |
| + * or more contributor license agreements. See the NOTICE file |
| + * distributed with this work for additional information |
| + * regarding copyright ownership. The ASF licenses this file |
| + * to you under the Apache License, Version 2.0 (the |
| + * "License"); you may not use this file except in compliance |
| + * with the License. You may obtain a copy of the License at |
| + * |
| + * http://www.apache.org/licenses/LICENSE-2.0 |
| + * |
| + * Unless required by applicable law or agreed to in writing, software |
| + * distributed under the License is distributed on an "AS IS" BASIS, |
| + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| + * See the License for the specific language governing permissions and |
| + * limitations under the License. |
| + */ |
| + package org.apache.oozie.command.coord; |
| + |
| +import java.util.Calendar; |
| + |
| +import org.apache.oozie.coord.CoordELFunctions; |
| +import org.apache.oozie.util.ELEvaluator; |
| + |
| +public class CoordELExtensions { |
| + private static final String PREFIX = "coordext:"; |
| + |
| + public static String ph1_today_echo(int hr, int min) { |
| + ELEvaluator eval = ELEvaluator.getCurrent(); |
| + eval.setVariable(".wrap", "true"); |
| + return PREFIX + "today(" + hr + ", " + min + ")"; // Unresolved |
| + } |
| + |
| + public static String ph2_today_inst(int hr, int min) throws Exception { |
| + Calendar nominalInstanceCal = CoordELFunctions.getEffectiveNominalTime(); |
| + if (nominalInstanceCal == null) { |
| + return ""; |
| + } |
| + |
| + Calendar dsInstanceCal = Calendar.getInstance(CoordELFunctions.getDatasetTZ()); |
| + dsInstanceCal.setTime(nominalInstanceCal.getTime()); |
| + dsInstanceCal.set(Calendar.HOUR_OF_DAY, hr); |
| + dsInstanceCal.set(Calendar.MINUTE, min); |
| + dsInstanceCal.set(Calendar.SECOND, 0); |
| + dsInstanceCal.set(Calendar.MILLISECOND, 0); |
| + |
| + int[] instCnt = new int[1]; |
| + Calendar compInstCal = CoordELFunctions |
| + .getCurrentInstance(dsInstanceCal.getTime(), instCnt); |
| + if (compInstCal == null) { |
| + return ""; |
| + } |
| + int dsInstanceCnt = instCnt[0]; |
| + |
| + compInstCal = CoordELFunctions.getCurrentInstance(nominalInstanceCal.getTime(), instCnt); |
| + if (compInstCal == null) { |
| + return ""; |
| + } |
| + int nominalInstanceCnt = instCnt[0]; |
| + |
| + return "coord:current(" + (dsInstanceCnt - nominalInstanceCnt) + ")"; |
| + } |
| + |
| + public static String ph2_today(int hr, int min) throws Exception { |
| + String inst = ph2_today_inst(hr, min); |
| + return evaluateCurrent(inst); |
| + } |
| + |
| + private static String evaluateCurrent(String curExpr) throws Exception { |
| + if (curExpr.equals("")) { |
| + return curExpr; |
| + } |
| + |
| + int inst = CoordCommandUtils.parseOneArg(curExpr); |
| + return CoordELFunctions.ph2_coord_current(inst); |
| + } |
| +} |
| \ No newline at end of file |
| Index: core/src/test/resources/oozie-site-coordel.xml |
| =================================================================== |
| --- core/src/test/resources/oozie-site-coordel.xml (revision 0) |
| +++ core/src/test/resources/oozie-site-coordel.xml (revision 0) |
| @@ -0,0 +1,65 @@ |
| +<?xml version="1.0" encoding="UTF-8"?> |
| +<!-- |
| + Licensed to the Apache Software Foundation (ASF) under one |
| + or more contributor license agreements. See the NOTICE file |
| + distributed with this work for additional information |
| + regarding copyright ownership. The ASF licenses this file |
| + to you under the Apache License, Version 2.0 (the |
| + "License"); you may not use this file except in compliance |
| + with the License. You may obtain a copy of the License at |
| + |
| + http://www.apache.org/licenses/LICENSE-2.0 |
| + |
| + Unless required by applicable law or agreed to in writing, software |
| + distributed under the License is distributed on an "AS IS" BASIS, |
| + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| + See the License for the specific language governing permissions and |
| + limitations under the License. |
| +--> |
| +<configuration> |
| + <property> |
| + <name>oozie.service.ELService.ext.functions.coord-job-submit-instances |
| + </name> |
| + <value> |
| + coordext:today=org.apache.oozie.command.coord.CoordELExtensions#ph1_today_echo |
| + </value> |
| + <description> |
| + EL functions declarations, separated by commas, |
| + format is [PREFIX:]NAME=CLASS#METHOD. |
| + This property is a |
| + convenience property to add extensions to the built in |
| + executors without having to |
| + include all the built in ones. |
| + </description> |
| + </property> |
| + <property> |
| + <name>oozie.service.ELService.ext.functions.coord-action-create-inst |
| + </name> |
| + <value> |
| + coordext:today=org.apache.oozie.command.coord.CoordELExtensions#ph2_today_inst |
| + </value> |
| + <description> |
| + EL functions declarations, separated by commas, |
| + format is [PREFIX:]NAME=CLASS#METHOD. |
| + This property is a |
| + convenience property to add extensions to the built in |
| + executors without having to |
| + include all the built in ones. |
| + </description> |
| + </property> |
| + <property> |
| + <name>oozie.service.ELService.ext.functions.coord-action-create |
| + </name> |
| + <value> |
| + coordext:today=org.apache.oozie.command.coord.CoordELExtensions#ph2_today |
| + </value> |
| + <description> |
| + EL functions declarations, separated by commas, |
| + format is [PREFIX:]NAME=CLASS#METHOD. |
| + This property is a |
| + convenience property to add extensions to the built in |
| + executors without having to |
| + include all the built in ones. |
| + </description> |
| + </property> |
| +</configuration> |
| \ No newline at end of file |
| Index: core/src/test/resources/coord-job-for-elext.xml |
| =================================================================== |
| --- core/src/test/resources/coord-job-for-elext.xml (revision 0) |
| +++ core/src/test/resources/coord-job-for-elext.xml (revision 0) |
| @@ -0,0 +1,63 @@ |
| +<!-- |
| + Licensed to the Apache Software Foundation (ASF) under one |
| + or more contributor license agreements. See the NOTICE file |
| + distributed with this work for additional information |
| + regarding copyright ownership. The ASF licenses this file |
| + to you under the Apache License, Version 2.0 (the |
| + "License"); you may not use this file except in compliance |
| + with the License. You may obtain a copy of the License at |
| + |
| + http://www.apache.org/licenses/LICENSE-2.0 |
| + |
| + Unless required by applicable law or agreed to in writing, software |
| + distributed under the License is distributed on an "AS IS" BASIS, |
| + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| + See the License for the specific language governing permissions and |
| + limitations under the License. |
| +--> |
| +<coordinator-app xmlns='uri:oozie:coordinator:0.2' name='NAME' |
| + frequency="1" start='2009-02-01T01:00Z' end='2009-02-03T23:59Z' |
| + timezone='UTC' freq_timeunit='DAY' end_of_duration='NONE'> |
| + <controls> |
| + <timeout>10</timeout> |
| + <concurrency>2</concurrency> |
| + <execution>LIFO</execution> |
| + </controls> |
| + <input-events> |
| + <data-in name='A' dataset='a'> |
| + <dataset name='a' frequency='1' initial-instance='2009-02-01T00:00Z' |
| + timezone='UTC' freq_timeunit='HOUR' end_of_duration='NONE'> |
| + <uri-template>file://#testDir/${YEAR}/${MONTH}/${DAY}/${HOUR} |
| + </uri-template> |
| + </dataset> |
| + <start-instance>${coordext:today(-1,0)}</start-instance> |
| + <end-instance>${coordext:today(0,0)}</end-instance> |
| + </data-in> |
| + </input-events> |
| + <output-events> |
| + <data-out name='LOCAL_A' dataset='local_a'> |
| + <dataset name='local_a' frequency='1' |
| + initial-instance='2009-02-01T00:00Z' timezone='UTC' |
| + freq_timeunit='HOUR' end_of_duration='NONE'> |
| + <uri-template>file://#testDir/${YEAR}/${DAY} |
| + </uri-template> |
| + </dataset> |
| + <instance>${coordext:today(0,0)}</instance> |
| + </data-out> |
| + </output-events> |
| + <action> |
| + <workflow> |
| + <app-path>hdfs:///tmp/workflows/</app-path> |
| + <configuration> |
| + <property> |
| + <name>inputA</name> |
| + <value>${coord:dataIn('A')}</value> |
| + </property> |
| + <property> |
| + <name>inputB</name> |
| + <value>${coord:dataOut('LOCAL_A')}</value> |
| + </property> |
| + </configuration> |
| + </workflow> |
| + </action> |
| +</coordinator-app> |
| \ No newline at end of file |
| Index: core/src/main/java/org/apache/oozie/command/coord/CoordCommandUtils.java |
| =================================================================== |
| --- core/src/main/java/org/apache/oozie/command/coord/CoordCommandUtils.java (revision 1485571) |
| +++ core/src/main/java/org/apache/oozie/command/coord/CoordCommandUtils.java (working copy) |
| @@ -63,28 +63,36 @@ |
| * <p/> |
| * |
| * @param function |
| - * @param event |
| - * @param appInst |
| - * @param conf |
| * @param restArg |
| * @return int instanceNumber |
| * @throws Exception |
| */ |
| - public static int getInstanceNumber(String function, Element event, SyncCoordAction appInst, Configuration conf, |
| - StringBuilder restArg) throws Exception { |
| - ELEvaluator eval = CoordELEvaluator |
| - .createInstancesELEvaluator("coord-action-create-inst", event, appInst, conf); |
| - String newFunc = CoordELFunctions.evalAndWrap(eval, function); |
| - int funcType = getFuncType(newFunc); |
| + public static int getInstanceNumber(String function, StringBuilder restArg) throws Exception { |
| + int funcType = getFuncType(function); |
| if (funcType == CURRENT || funcType == LATEST) { |
| - return parseOneArg(newFunc); |
| + return parseOneArg(function); |
| } |
| else { |
| - return parseMoreArgs(newFunc, restArg); |
| + return parseMoreArgs(function, restArg); |
| } |
| } |
| |
| - private static int parseOneArg(String funcName) throws Exception { |
| + /** |
| + * Evaluates function for coord-action-create-inst tag |
| + * @param event |
| + * @param appInst |
| + * @param conf |
| + * @param function |
| + * @return evaluation result |
| + * @throws Exception |
| + */ |
| + private static String evaluateInstanceFunction(Element event, SyncCoordAction appInst, Configuration conf, |
| + String function) throws Exception { |
| + ELEvaluator eval = CoordELEvaluator.createInstancesELEvaluator("coord-action-create-inst", event, appInst, conf); |
| + return CoordELFunctions.evalAndWrap(eval, function); |
| + } |
| + |
| + public static int parseOneArg(String funcName) throws Exception { |
| int firstPos = funcName.indexOf("("); |
| int lastPos = funcName.lastIndexOf(")"); |
| if (firstPos >= 0 && lastPos > firstPos) { |
| @@ -166,15 +174,15 @@ |
| Element eStartInst = event.getChild("start-instance", event.getNamespace()); |
| Element eEndInst = event.getChild("end-instance", event.getNamespace()); |
| if (eStartInst != null && eEndInst != null) { |
| - String strStart = eStartInst.getTextTrim(); |
| - String strEnd = eEndInst.getTextTrim(); |
| + String strStart = evaluateInstanceFunction(event, appInst, conf, eStartInst.getTextTrim()); |
| + String strEnd = evaluateInstanceFunction(event, appInst, conf, eEndInst.getTextTrim()); |
| checkIfBothSameType(strStart, strEnd); |
| StringBuilder restArg = new StringBuilder(); // To store rest |
| // arguments for |
| // future |
| // function |
| - int startIndex = getInstanceNumber(strStart, event, appInst, conf, restArg); |
| + int startIndex = getInstanceNumber(strStart, restArg); |
| restArg.delete(0, restArg.length()); |
| - int endIndex = getInstanceNumber(strEnd, event, appInst, conf, restArg); |
| + int endIndex = getInstanceNumber(strEnd, restArg); |
| if (startIndex > endIndex) { |
| throw new CommandException(ErrorCode.E1010, |
| Index: core/src/main/java/org/apache/oozie/coord/CoordELFunctions.java |
| =================================================================== |
| --- core/src/main/java/org/apache/oozie/coord/CoordELFunctions.java (revision 1485571) |
| +++ core/src/main/java/org/apache/oozie/coord/CoordELFunctions.java (working copy) |
| @@ -952,7 +952,7 @@ |
| * @return current instance i.e. current(0) returns null if effectiveTime is earlier than Initial Instance time of |
| * the dataset. |
| */ |
| - private static Calendar getCurrentInstance(Date effectiveTime, int instanceCount[]) { |
| + public static Calendar getCurrentInstance(Date effectiveTime, int instanceCount[]) { |
| Date datasetInitialInstance = getInitialInstance(); |
| TimeUnit dsTimeUnit = getDSTimeUnit(); |
| TimeZone dsTZ = getDatasetTZ(); |
| @@ -1294,7 +1294,7 @@ |
| return current; |
| } |
| |
| - private static Calendar getEffectiveNominalTime() { |
| + public static Calendar getEffectiveNominalTime() { |
| Date datasetInitialInstance = getInitialInstance(); |
| TimeZone dsTZ = getDatasetTZ(); |
| // Convert Date to Calendar for corresponding TZ |
| @@ -1356,7 +1356,7 @@ |
| /** |
| * @return dataset TimeZone |
| */ |
| - private static TimeZone getDatasetTZ() { |
| + public static TimeZone getDatasetTZ() { |
| ELEvaluator eval = ELEvaluator.getCurrent(); |
| return getDatasetTZ(eval); |
| } |