blob: c35437c13cd7c3e429525536accbfe84bf4e766e [file] [log] [blame]
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);
}