Oozie-参数表达式体系

ELService 服务是用于初始化el计算的服务,oozie的参数计算使用的是 org.apache.commons.el 的 JSP Expression Language Evaluator。功能可以做到,变量值的动态计算,支持oozie这次的计算表达式。这些表达式是固定的,需要在初始化的时候加载到oozie中。现在来看看代码:

oozie将对参数的计算封装成 ELEvaluator

private Context context;
private ExpressionEvaluatorImpl evaluator = new ExpressionEvaluatorImpl();

ExpressionEvaluatorImpl ** 是common包中的计算实现。context** 继承了
VariableResolver,FunctionMapper

/**
 * Provides functions and variables for the EL evaluator. <p/> All functions and variables in the context of an EL
 * evaluator are accessible from EL expressions.
 */
public static class Context implements VariableResolver, FunctionMapper {
    private Map<String, Object> vars;
    private Map<String, Method> functions;
    /**
     * Create an empty context.
     */
    public Context() {
        vars = new HashMap<String, Object>();
        functions = new HashMap<String, Method>();
    }
    /**
     * Add variables to the context. <p/>
     *
     * @param vars variables to add to the context.
     */
    public void setVariables(Map<String, Object> vars) {
        this.vars.putAll(vars);
    }
    /**
     * Add a variable to the context. <p/>
     *
     * @param name variable name.
     * @param value variable value.
     */
    public void setVariable(String name, Object value) {
        vars.put(name, value);
    }
    /**
     * Return a variable from the context. <p/>
     *
     * @param name variable name.
     * @return the variable value.
     */
    public Object getVariable(String name) {
        return vars.get(name);
    }
    /**
     * Add a function to the context. <p/>
     *
     * @param prefix function prefix.
     * @param functionName function name.
     * @param method method that will be invoked for the function, it must be a static and public method.
     */
    public void addFunction(String prefix, String functionName, Method method) {
        if ((method.getModifiers() & (Modifier.PUBLIC | Modifier.STATIC)) != (Modifier.PUBLIC | Modifier.STATIC)) {
            throw new IllegalArgumentException(XLog.format("Method[{0}] must be public and static", method));
        }
        prefix = (prefix.length() > 0) ? prefix + ":" : "";
        functions.put(prefix + functionName, method);
    }
    /**
     * Resolve a variable name. Used by the EL evaluator implemenation. <p/>
     *
     * @param name variable name.
     * @return the variable value.
     * @throws ELException thrown if the variable is not defined in the context.
     */
    public Object resolveVariable(String name) throws ELException {
        if (!vars.containsKey(name)) {
            throw new ELException(XLog.format("variable [{0}] cannot be resolved", name));
        }
        return vars.get(name);
    }
    /**
     * Resolve a function prefix:name. Used by the EL evaluator implementation. <p/>
     *
     * @param prefix function prefix.
     * @param name function name.
     * @return the method associated to the function.
     */
    public Method resolveFunction(String prefix, String name) {
        if (prefix.length() > 0) {
            name = prefix + ":" + name;
        }
        return functions.get(name);
    }
}

这里的 Map中的key是方法或者是数值的别名。

/**
 * Evaluate an EL expression. <p/>
 *
 * @param expr EL expression to evaluate.
 * @param clazz return type of the EL expression.
 * @return the object the EL expression evaluated to.
 * @throws Exception thrown if an EL function failed due to a transient error or EL expression could not be
 * evaluated.
 */
@SuppressWarnings({"unchecked", "deprecation"})
public <T> T evaluate(String expr, Class<T> clazz) throws Exception {
    ELEvaluator existing = current.get();
    try {
        current.set(this);
        return (T) evaluator.evaluate(expr, clazz, context, context);
    }
    catch (ELException ex) {
        if (ex.getRootCause() instanceof Exception) {
            throw (Exception) ex.getRootCause();
        }
        else {
            throw ex;
        }
    }
    finally {
        current.set(existing);
    }
}

表达式计算的具体实现方法;

正如前面介绍组件的时候,可以看到oozie内置了大量的表达式运算。现在我们来看看他们的具体实现;

<!-- Workflow specifics -->
    <property>
        <name>oozie.service.ELService.constants.workflow</name>
        <value>
            KB=org.apache.oozie.util.ELConstantsFunctions#KB,
            MB=org.apache.oozie.util.ELConstantsFunctions#MB,
            GB=org.apache.oozie.util.ELConstantsFunctions#GB,
            TB=org.apache.oozie.util.ELConstantsFunctions#TB,
            PB=org.apache.oozie.util.ELConstantsFunctions#PB,
            RECORDS=org.apache.oozie.action.hadoop.HadoopELFunctions#RECORDS,
            MAP_IN=org.apache.oozie.action.hadoop.HadoopELFunctions#MAP_IN,
            MAP_OUT=org.apache.oozie.action.hadoop.HadoopELFunctions#MAP_OUT,
            REDUCE_IN=org.apache.oozie.action.hadoop.HadoopELFunctions#REDUCE_IN,
            REDUCE_OUT=org.apache.oozie.action.hadoop.HadoopELFunctions#REDUCE_OUT,
            GROUPS=org.apache.oozie.action.hadoop.HadoopELFunctions#GROUPS 
       </value>
        <description>
            EL constant declarations, separated by commas, format is [PREFIX:]NAME=CLASS#CONSTANT.
        </description>
    </property>
<property>
    <name>oozie.service.ELService.functions.workflow</name>
    <value>
        firstNotNull=org.apache.oozie.util.ELConstantsFunctions#firstNotNull,
        concat=org.apache.oozie.util.ELConstantsFunctions#concat,
        replaceAll=org.apache.oozie.util.ELConstantsFunctions#replaceAll,
        appendAll=org.apache.oozie.util.ELConstantsFunctions#appendAll,
        trim=org.apache.oozie.util.ELConstantsFunctions#trim,
        timestamp=org.apache.oozie.util.ELConstantsFunctions#timestamp,
        urlEncode=org.apache.oozie.util.ELConstantsFunctions#urlEncode,        toJsonStr=org.apache.oozie.util.ELConstantsFunctions#toJsonStr,
        toPropertiesStr=org.apache.oozie.util.ELConstantsFunctions#toPropertiesStr,
        toConfigurationStr=org.apache.oozie.util.ELConstantsFunctions#toConfigurationStr,
        wf:id=org.apache.oozie.DagELFunctions#wf_id,
        wf:name=org.apache.oozie.DagELFunctions#wf_name,
        wf:appPath=org.apache.oozie.DagELFunctions#wf_appPath,
        wf:conf=org.apache.oozie.DagELFunctions#wf_conf,
        wf:user=org.apache.oozie.DagELFunctions#wf_user,
        wf:group=org.apache.oozie.DagELFunctions#wf_group,
        wf:callback=org.apache.oozie.DagELFunctions#wf_callback,
        wf:transition=org.apache.oozie.DagELFunctions#wf_transition,
        wf:lastErrorNode=org.apache.oozie.DagELFunctions#wf_lastErrorNode,
        wf:errorCode=org.apache.oozie.DagELFunctions#wf_errorCode,
        wf:errorMessage=org.apache.oozie.DagELFunctions#wf_errorMessage,
        wf:run=org.apache.oozie.DagELFunctions#wf_run,
        wf:actionData=org.apache.oozie.DagELFunctions#wf_actionData,
        wf:actionExternalId=org.apache.oozie.DagELFunctions#wf_actionExternalId,
        wf:actionTrackerUri=org.apache.oozie.DagELFunctions#wf_actionTrackerUri,
        wf:actionExternalStatus=org.apache.oozie.DagELFunctions#wf_actionExternalStatus,
        hadoop:counters=org.apache.oozie.action.hadoop.HadoopELFunctions#hadoop_counters,
        hadoop:conf=org.apache.oozie.action.hadoop.HadoopELFunctions#hadoop_conf,
        fs:exists=org.apache.oozie.action.hadoop.FsELFunctions#fs_exists,
        fs:isDir=org.apache.oozie.action.hadoop.FsELFunctions#fs_isDir,
        fs:dirSize=org.apache.oozie.action.hadoop.FsELFunctions#fs_dirSize,
        fs:fileSize=org.apache.oozie.action.hadoop.FsELFunctions#fs_fileSize,
        fs:blockSize=org.apache.oozie.action.hadoop.FsELFunctions#fs_blockSize,
        hcat:exists=org.apache.oozie.coord.HCatELFunctions#hcat_exists
    </value>
    <description>
        EL functions declarations, separated by commas, format is [PREFIX:]NAME=CLASS#METHOD.
    </description>
</property>

现在看几个具体实现:

wf:user=org.apache.oozie.DagELFunctions#wf_user,

/**
 * Return the job owner user name.
 *
 * @return the job owner user name.
 */
public static String wf_user() {
    return getWorkflow().getUser();
}

public static WorkflowJobBean getWorkflow() {
    ELEvaluator eval = ELEvaluator.getCurrent();
    return (WorkflowJobBean) eval.getVariable(WORKFLOW);
}


  hadoop:counters=org.apache.oozie.action.hadoop.HadoopELFunctions#hadoop_counters


public static Map<String, Map<String, Long>> hadoop_counters(String nodeName) throws ELEvaluationException {
    WorkflowInstance instance = DagELFunctions.getWorkflow().getWorkflowInstance();
    Object obj = instance.getTransientVar(nodeName + WorkflowInstance.NODE_VAR_SEPARATOR + HADOOP_COUNTERS);
    Map<String, Map<String, Long>> counters = (Map<String, Map<String, Long>>) obj;
    if (counters == null) {
        counters = getCounters(nodeName);
        // In Hadoop 0.23 they deprecated 'org.apache.hadoop.mapred.Task$Counter' and they REMOVED IT
        // Here we are getting the new Name and inserting it using the old name if the old name is not found
        if (counters.get(RECORDS) == null) {
            counters.put(RECORDS, counters.get(RECORDS_023));
        }
        instance.setTransientVar(nodeName + WorkflowInstance.NODE_VAR_SEPARATOR + HADOOP_COUNTERS, counters);
    }
    return counters;
}


fs:exists=org.apache.oozie.action.hadoop.FsELFunctions#fs_exists

/**
 * Return if a path exists.
 *
 * @param pathUri file system path uri.
 * @return <code>true</code> if the path exists, <code>false</code> if it does not.
 * @throws Exception
 */
public static boolean fs_exists(String pathUri) throws Exception {
    URI uri = new URI(pathUri);
    String path = uri.getPath();
    FileSystem fs = getFileSystem(uri);
    return fs.exists(new Path(path));
}



hcat:exists=org.apache.oozie.coord.HCatELFunctions#hcat_exists


/**
 * Return true if partitions exists or false if not.
 *
 * @param uri hcatalog partition uri.
 * @return <code>true</code> if the uri exists, <code>false</code> if it does not.
 * @throws Exception
 */
public static boolean hcat_exists(String uri) throws Exception {
    URI hcatURI = new URI(uri);
    URIHandlerService uriService = Services.get().get(URIHandlerService.class);
    URIHandler handler = uriService.getURIHandler(hcatURI);
    WorkflowJob workflow = DagELFunctions.getWorkflow();
    String user = workflow.getUser();
    return handler.exists(hcatURI, EMPTY_CONF, user);
}

   <!-- Resolve SLA information during Workflow job submission --><property>
       <name>oozie.service.ELService.constants.wf-sla-submit</name>
       <value>
           MINUTES=org.apache.oozie.util.ELConstantsFunctions#SUBMIT_MINUTES,
           HOURS=org.apache.oozie.util.ELConstantsFunctions#SUBMIT_HOURS,
           DAYS=org.apache.oozie.util.ELConstantsFunctions#SUBMIT_DAYS
           </value>
       <description>
           EL constant declarations, separated by commas, format is [PREFIX:]NAME=CLASS#CONSTANT.
       </description>
   </property>


<property>
    <name>oozie.service.ELService.functions.coord-job-submit-freq</name>
    <value>
        coord:days=org.apache.oozie.coord.CoordELFunctions#ph1_coord_days,
        coord:months=org.apache.oozie.coord.CoordELFunctions#ph1_coord_months,
        coord:hours=org.apache.oozie.coord.CoordELFunctions#ph1_coord_hours,
        coord:minutes=org.apache.oozie.coord.CoordELFunctions#ph1_coord_minutes,
        coord:endOfDays=org.apache.oozie.coord.CoordELFunctions#ph1_coord_endOfDays,
        coord:endOfMonths=org.apache.oozie.coord.CoordELFunctions#ph1_coord_endOfMonths,
        coord:conf=org.apache.oozie.coord.CoordELFunctions#coord_conf,       
 coord:user=org.apache.oozie.coord.CoordELFunctions#coord_user,
        hadoop:conf=org.apache.oozie.action.hadoop.HadoopELFunctions#hadoop_conf
    </value>
    <description>
        EL functions declarations, separated by commas, format is [PREFIX:]NAME=CLASS#METHOD.
    </description>
</property>

现在看几个具体实现:

coord:days=org.apache.oozie.coord.CoordELFunctions#ph1_coord_days

public static int ph1_coord_days(int val) {
    val = ParamChecker.checkGTZero(val, "n");
    ELEvaluator eval = ELEvaluator.getCurrent();
    eval.setVariable("timeunit", TimeUnit.DAY);
    eval.setVariable("endOfDuration", TimeUnit.NONE);
    return val;
}

<property>
    <name>oozie.service.ELService.functions.coord-job-wait-timeout</name>
    <value>
        coord:days=org.apache.oozie.coord.CoordELFunctions#ph1_coord_days,
        coord:months=org.apache.oozie.coord.CoordELFunctions#ph1_coord_months,
        coord:hours=org.apache.oozie.coord.CoordELFunctions#ph1_coord_hours,
        coord:minutes=org.apache.oozie.coord.CoordELFunctions#ph1_coord_minutes,
        hadoop:conf=org.apache.oozie.action.hadoop.HadoopELFunctions#hadoop_conf
    </value>
    <description>
        EL functions declarations, separated by commas, format is [PREFIX:]NAME=CLASS#METHOD.
    </description>
</property>


<!-- EL Evalautor setup to resolve mainly all constants/variables - no EL functions is resolved -->
    <property>
        <name>oozie.service.ELService.constants.coord-job-submit-nofuncs</name>
        <value>
            MINUTE=org.apache.oozie.coord.CoordELConstants#SUBMIT_MINUTE,
            HOUR=org.apache.oozie.coord.CoordELConstants#SUBMIT_HOUR,
            DAY=org.apache.oozie.coord.CoordELConstants#SUBMIT_DAY,
            MONTH=org.apache.oozie.coord.CoordELConstants#SUBMIT_MONTH,
            YEAR=org.apache.oozie.coord.CoordELConstants#SUBMIT_YEAR
        </value>
        <description>
            EL constant declarations, separated by commas, format is [PREFIX:]NAME=CLASS#CONSTANT.
        </description>
    </property>


<property>
    <name>oozie.service.ELService.functions.coord-job-submit-nofuncs</name>
    <value>
        coord:conf=org.apache.oozie.coord.CoordELFunctions#coord_conf,
        coord:user=org.apache.oozie.coord.CoordELFunctions#coord_user,
        hadoop:conf=org.apache.oozie.action.hadoop.HadoopELFunctions#hadoop_conf
    </value>
    <description>
        EL functions declarations, separated by commas, format is [PREFIX:]NAME=CLASS#METHOD.
    </description>
</property>


<property>
    <name>oozie.service.ELService.functions.coord-job-submit-instances</name>
    <value>
        coord:hoursInDay=org.apache.oozie.coord.CoordELFunctions#ph1_coord_hoursInDay_echo,
        coord:daysInMonth=org.apache.oozie.coord.CoordELFunctions#ph1_coord_daysInMonth_echo,
        coord:tzOffset=org.apache.oozie.coord.CoordELFunctions#ph1_coord_tzOffset_echo,
        coord:current=org.apache.oozie.coord.CoordELFunctions#ph1_coord_current_echo,
        coord:currentRange=org.apache.oozie.coord.CoordELFunctions#ph1_coord_currentRange_echo,
        coord:offset=org.apache.oozie.coord.CoordELFunctions#ph1_coord_offset_echo,
        coord:latest=org.apache.oozie.coord.CoordELFunctions#ph1_coord_latest_echo,
        coord:latestRange=org.apache.oozie.coord.CoordELFunctions#ph1_coord_latestRange_echo,
        coord:future=org.apache.oozie.coord.CoordELFunctions#ph1_coord_future_echo,
        coord:futureRange=org.apache.oozie.coord.CoordELFunctions#ph1_coord_futureRange_echo,
        coord:formatTime=org.apache.oozie.coord.CoordELFunctions#ph1_coord_formatTime_echo,
        coord:conf=org.apache.oozie.coord.CoordELFunctions#coord_conf,
        coord:user=org.apache.oozie.coord.CoordELFunctions#coord_user,       
 coord:absolute=org.apache.oozie.coord.CoordELFunctions#ph1_coord_absolute_echo,
        hadoop:conf=org.apache.oozie.action.hadoop.HadoopELFunctions#hadoop_conf
    </value>
    <description>
        EL functions declarations, separated by commas, format is [PREFIX:]NAME=CLASS#METHOD.
    </description>
</property>

现在看几个具体实现:

coord:current=org.apache.oozie.coord.CoordELFunctions#ph1_coord_current_echo

public static String ph1_coord_current_echo(String n) {
    return echoUnResolved("current", n);
}

private static String echoUnResolved(String functionName, String n) {
    return echoUnResolvedPre(functionName, n, "coord:");
}

private static String echoUnResolvedPre(String functionName, String n, String prefix) {
    ELEvaluator eval = ELEvaluator.getCurrent();
    eval.setVariable(".wrap", "true");
    return prefix + functionName + "(" + n + ")"; // Unresolved
}


<property>
    <name>oozie.service.ELService.functions.coord-job-submit-data</name>
    <value>
        coord:dataIn=org.apache.oozie.coord.CoordELFunctions#ph1_coord_dataIn_echo,
        coord:dataOut=org.apache.oozie.coord.CoordELFunctions#ph1_coord_dataOut_echo,
        coord:nominalTime=org.apache.oozie.coord.CoordELFunctions#ph1_coord_nominalTime_echo_wrap,
        coord:actualTime=org.apache.oozie.coord.CoordELFunctions#ph1_coord_actualTime_echo_wrap,
        coord:dateOffset=org.apache.oozie.coord.CoordELFunctions#ph1_coord_dateOffset_echo,
        coord:dateTzOffset=org.apache.oozie.coord.CoordELFunctions#ph1_coord_dateTzOffset_echo,
        coord:formatTime=org.apache.oozie.coord.CoordELFunctions#ph1_coord_formatTime_echo,
        coord:actionId=org.apache.oozie.coord.CoordELFunctions#ph1_coord_actionId_echo,
        coord:name=org.apache.oozie.coord.CoordELFunctions#ph1_coord_name_echo,
        coord:conf=org.apache.oozie.coord.CoordELFunctions#coord_conf, 
       coord:user=org.apache.oozie.coord.CoordELFunctions#coord_user,
        coord:databaseIn=org.apache.oozie.coord.HCatELFunctions#ph1_coord_databaseIn_echo,
        coord:databaseOut=org.apache.oozie.coord.HCatELFunctions#ph1_coord_databaseOut_echo,
        coord:tableIn=org.apache.oozie.coord.HCatELFunctions#ph1_coord_tableIn_echo,
        coord:tableOut=org.apache.oozie.coord.HCatELFunctions#ph1_coord_tableOut_echo,
        coord:dataInPartitionFilter=org.apache.oozie.coord.HCatELFunctions#ph1_coord_dataInPartitionFilter_echo,
        coord:dataInPartitionMin=org.apache.oozie.coord.HCatELFunctions#ph1_coord_dataInPartitionMin_echo,
        coord:dataInPartitionMax=org.apache.oozie.coord.HCatELFunctions#ph1_coord_dataInPartitionMax_echo,
        coord:dataInPartitions=org.apache.oozie.coord.HCatELFunctions#ph1_coord_dataInPartitions_echo,
        coord:dataOutPartitions=org.apache.oozie.coord.HCatELFunctions#ph1_coord_dataOutPartitions_echo,
        coord:dataOutPartitionValue=org.apache.oozie.coord.HCatELFunctions#ph1_coord_dataOutPartitionValue_echo,
        hadoop:conf=org.apache.oozie.action.hadoop.HadoopELFunctions#hadoop_conf
    </value>
    <description>
        EL functions declarations, separated by commas, format is [PREFIX:]NAME=CLASS#METHOD.
    </description>
</property>

现在看几个具体实现:

coord:dataIn=org.apache.oozie.coord.CoordELFunctions#ph1_coord_dataIn_echo

public static String ph1_coord_dataIn_echo(String n) {
    ELEvaluator eval = ELEvaluator.getCurrent();
    String val = (String) eval.getVariable("oozie.dataname." + n);
    if (val == null || val.equals("data-in") == false) {
        XLog.getLog(CoordELFunctions.class).error("data_in_name " + n + " is not valid");
        throw new RuntimeException("data_in_name " + n + " is not valid");
    }
    return echoUnResolved("dataIn", "'" + n + "'");
}

<property>
       <name>oozie.service.ELService.constants.coord-sla-submit</name>
       <value>
           MINUTES=org.apache.oozie.coord.CoordELConstants#SUBMIT_MINUTES,
           HOURS=org.apache.oozie.coord.CoordELConstants#SUBMIT_HOURS,
           DAYS=org.apache.oozie.coord.CoordELConstants#SUBMIT_DAYS
           </value>
       <description>
           EL constant declarations, separated by commas, format is [PREFIX:]NAME=CLASS#CONSTANT.
       </description>
   </property>


<property>
    <name>oozie.service.ELService.functions.coord-sla-submit</name>
    <value>        coord:dataOut=org.apache.oozie.coord.CoordELFunctions#ph1_coord_dataOut_echo,
        coord:nominalTime=org.apache.oozie.coord.CoordELFunctions#ph1_coord_nominalTime_echo_fixed,
        coord:actualTime=org.apache.oozie.coord.CoordELFunctions#ph1_coord_actualTime_echo_wrap,
        coord:dateOffset=org.apache.oozie.coord.CoordELFunctions#ph1_coord_dateOffset_echo,
        coord:dateTzOffset=org.apache.oozie.coord.CoordELFunctions#ph1_coord_dateTzOffset_echo,
        coord:formatTime=org.apache.oozie.coord.CoordELFunctions#ph1_coord_formatTime_echo,
        coord:actionId=org.apache.oozie.coord.CoordELFunctions#ph1_coord_actionId_echo,
        coord:name=org.apache.oozie.coord.CoordELFunctions#ph1_coord_name_echo,
        coord:conf=org.apache.oozie.coord.CoordELFunctions#coord_conf,
       coord:user=org.apache.oozie.coord.CoordELFunctions#coord_user,
        coord:databaseOut=org.apache.oozie.coord.HCatELFunctions#ph1_coord_databaseOut_echo,
        coord:tableOut=org.apache.oozie.coord.HCatELFunctions#ph1_coord_tableOut_echo,
        coord:dataOutPartitions=org.apache.oozie.coord.HCatELFunctions#ph1_coord_dataOutPartitions_echo,
        coord:dataOutPartitionValue=org.apache.oozie.coord.HCatELFunctions#ph1_coord_dataOutPartitionValue_echo,
        hadoop:conf=org.apache.oozie.action.hadoop.HadoopELFunctions#hadoop_conf
    </value>
    <description>
        EL functions declarations, separated by commas, format is [PREFIX:]NAME=CLASS#METHOD.
    </description>
</property>


<property>
    <name>oozie.service.ELService.functions.coord-action-create</name>
    <value>
        coord:hoursInDay=org.apache.oozie.coord.CoordELFunctions#ph2_coord_hoursInDay,
        coord:daysInMonth=org.apache.oozie.coord.CoordELFunctions#ph2_coord_daysInMonth,
        coord:tzOffset=org.apache.oozie.coord.CoordELFunctions#ph2_coord_tzOffset,
        coord:current=org.apache.oozie.coord.CoordELFunctions#ph2_coord_current,
        coord:currentRange=org.apache.oozie.coord.CoordELFunctions#ph2_coord_currentRange,
        coord:offset=org.apache.oozie.coord.CoordELFunctions#ph2_coord_offset,
        coord:latest=org.apache.oozie.coord.CoordELFunctions#ph2_coord_latest_echo,
        coord:latestRange=org.apache.oozie.coord.CoordELFunctions#ph2_coord_latestRange_echo,
        coord:future=org.apache.oozie.coord.CoordELFunctions#ph2_coord_future_echo,
        coord:futureRange=org.apache.oozie.coord.CoordELFunctions#ph2_coord_futureRange_echo,
        coord:actionId=org.apache.oozie.coord.CoordELFunctions#ph2_coord_actionId,
        coord:name=org.apache.oozie.coord.CoordELFunctions#ph2_coord_name,
        coord:formatTime=org.apache.oozie.coord.CoordELFunctions#ph2_coord_formatTime,
        coord:conf=org.apache.oozie.coord.CoordELFunctions#coord_conf,
        coord:user=org.apache.oozie.coord.CoordELFunctions#coord_user,
        coord:absolute=org.apache.oozie.coord.CoordELFunctions#ph2_coord_absolute_echo,
        coord:absoluteRange=org.apache.oozie.coord.CoordELFunctions#ph2_coord_absolute_range,
        hadoop:conf=org.apache.oozie.action.hadoop.HadoopELFunctions#hadoop_conf
    </value>
    <description>
        EL functions declarations, separated by commas, format is [PREFIX:]NAME=CLASS#METHOD.
    </description>
</property>

现在看几个具体实现:

coord:hoursInDay=org.apache.oozie.coord.CoordELFunctions#ph2_coord_hoursInDay


/**
 * Determine how many hours is on the date of n-th dataset instance. <p/> It depends on: <p/> 1. Data set frequency
 * <p/> 2. Data set Time unit (day, month, minute) <p/> 3. Data set Time zone/DST <p/> 4. End Day/Month flag <p/> 5.
 * Data set initial instance <p/> 6. Action Creation Time
 *
 * @param n instance count <p/> domain: n is integer
 * @return number of hours on that day <p/> returns -1 means n-th instance is earlier than Initial-Instance of DS
 * @throws Exception 
*/

public static int ph2_coord_hoursInDay(int n) throws Exception {
    int datasetFrequency = (int) getDSFrequency();
    // /Calendar nominalInstanceCal =
    // getCurrentInstance(getActionCreationtime());
    Calendar nominalInstanceCal = getEffectiveNominalTime();
    if (nominalInstanceCal == null) {
        return -1;
    }
    nominalInstanceCal.add(getDSTimeUnit().getCalendarUnit(), datasetFrequency * n);
    /*
     * if (nominalInstanceCal.getTime().compareTo(getInitialInstance()) < 0)
     * { return -1; } 
    */
    nominalInstanceCal.setTimeZone(getDatasetTZ());// Use Dataset TZ
    // DateUtils.moveToEnd(nominalInstanceCal, getDSEndOfFlag());
    return DateUtils.hoursInDay(nominalInstanceCal);
}


coord:current=org.apache.oozie.coord.CoordELFunctions#ph2_coord_current


/**
 * Determine the date-time in Oozie processing timezone of n-th dataset instance. <p/> It depends on: <p/> 1.
 * Data set frequency <p/> 2.
 * Data set Time unit (day, month, minute) <p/> 3. Data set Time zone/DST <p/> 4. End Day/Month flag <p/> 5. Data
 * set initial instance <p/> 6. Action Creation Time
 *
 * @param n instance count domain: n is integer
 * @return date-time in Oozie processing timezone of the n-th instance returns 'null' means n-th instance is
 * earlier than Initial-Instance of DS
 * @throws Exception
 */
public static String ph2_coord_current(int n) throws Exception {
    if (isSyncDataSet()) {
 // For Sync Dataset
        return coord_current_sync(n);
    }
    else {
        throw new UnsupportedOperationException("Asynchronous Dataset is not supported yet");
    }
}



coord:formatTime=org.apache.oozie.coord.CoordELFunctions#ph2_coord_formatTime


/**
 * Convert from standard date-time formatting to a desired format.
 * <p/>
 * @param dateTimeStr - A timestamp in standard (ISO8601) format.
 * @param format - A string representing the desired format.
 * @return coordinator action creation or materialization date time
 * @throws Exception if unable to format the Date object to String */
public static String ph2_coord_formatTime(String dateTimeStr, String format)
        throws Exception {
    Date dateTime = DateUtils.parseDateOozieTZ(dateTimeStr);
    return DateUtils.formatDateCustom(dateTime, format);
}



<property>
    <name>oozie.service.ELService.functions.coord-action-create-inst</name>
    <value>
        coord:hoursInDay=org.apache.oozie.coord.CoordELFunctions#ph2_coord_hoursInDay,
        coord:daysInMonth=org.apache.oozie.coord.CoordELFunctions#ph2_coord_daysInMonth,
        coord:tzOffset=org.apache.oozie.coord.CoordELFunctions#ph2_coord_tzOffset,
        coord:current=org.apache.oozie.coord.CoordELFunctions#ph2_coord_current_echo,
        coord:currentRange=org.apache.oozie.coord.CoordELFunctions#ph2_coord_currentRange_echo,
        coord:offset=org.apache.oozie.coord.CoordELFunctions#ph2_coord_offset_echo,
        coord:latest=org.apache.oozie.coord.CoordELFunctions#ph2_coord_latest_echo,
        coord:latestRange=org.apache.oozie.coord.CoordELFunctions#ph2_coord_latestRange_echo,
        coord:future=org.apache.oozie.coord.CoordELFunctions#ph2_coord_future_echo,
        coord:futureRange=org.apache.oozie.coord.CoordELFunctions#ph2_coord_futureRange_echo,
        coord:formatTime=org.apache.oozie.coord.CoordELFunctions#ph2_coord_formatTime,
        coord:conf=org.apache.oozie.coord.CoordELFunctions#coord_conf,        
coord:user=org.apache.oozie.coord.CoordELFunctions#coord_user,
        coord:absolute=org.apache.oozie.coord.CoordELFunctions#ph2_coord_absolute_echo,
        coord:absoluteRange=org.apache.oozie.coord.CoordELFunctions#ph2_coord_absolute_range,
        hadoop:conf=org.apache.oozie.action.hadoop.HadoopELFunctions#hadoop_conf
    </value>
    <description>
        EL functions declarations, separated by commas, format is [PREFIX:]NAME=CLASS#METHOD.
    </description>
</property>



<property>
    <name>oozie.service.ELService.functions.coord-action-start</name>
    <value>
        coord:hoursInDay=org.apache.oozie.coord.CoordELFunctions#ph3_coord_hoursInDay,
        coord:daysInMonth=org.apache.oozie.coord.CoordELFunctions#ph3_coord_daysInMonth,
        coord:tzOffset=org.apache.oozie.coord.CoordELFunctions#ph3_coord_tzOffset,
        coord:latest=org.apache.oozie.coord.CoordELFunctions#ph3_coord_latest,
        coord:latestRange=org.apache.oozie.coord.CoordELFunctions#ph3_coord_latestRange,
        coord:future=org.apache.oozie.coord.CoordELFunctions#ph3_coord_future,
        coord:futureRange=org.apache.oozie.coord.CoordELFunctions#ph3_coord_futureRange,
        coord:dataIn=org.apache.oozie.coord.CoordELFunctions#ph3_coord_dataIn,
        coord:dataOut=org.apache.oozie.coord.CoordELFunctions#ph3_coord_dataOut,
        coord:nominalTime=org.apache.oozie.coord.CoordELFunctions#ph3_coord_nominalTime,
        coord:actualTime=org.apache.oozie.coord.CoordELFunctions#ph3_coord_actualTime,
        coord:dateOffset=org.apache.oozie.coord.CoordELFunctions#ph3_coord_dateOffset,
        coord:dateTzOffset=org.apache.oozie.coord.CoordELFunctions#ph3_coord_dateTzOffset,
        coord:formatTime=org.apache.oozie.coord.CoordELFunctions#ph3_coord_formatTime,
        coord:actionId=org.apache.oozie.coord.CoordELFunctions#ph3_coord_actionId,
        coord:name=org.apache.oozie.coord.CoordELFunctions#ph3_coord_name,
        coord:conf=org.apache.oozie.coord.CoordELFunctions#coord_conf,
       coord:user=org.apache.oozie.coord.CoordELFunctions#coord_user,
        coord:databaseIn=org.apache.oozie.coord.HCatELFunctions#ph3_coord_databaseIn,
        coord:databaseOut=org.apache.oozie.coord.HCatELFunctions#ph3_coord_databaseOut,
        coord:tableIn=org.apache.oozie.coord.HCatELFunctions#ph3_coord_tableIn,
        coord:tableOut=org.apache.oozie.coord.HCatELFunctions#ph3_coord_tableOut,
        coord:dataInPartitionFilter=org.apache.oozie.coord.HCatELFunctions#ph3_coord_dataInPartitionFilter,
        coord:dataInPartitionMin=org.apache.oozie.coord.HCatELFunctions#ph3_coord_dataInPartitionMin,
        coord:dataInPartitionMax=org.apache.oozie.coord.HCatELFunctions#ph3_coord_dataInPartitionMax,
        coord:dataInPartitions=org.apache.oozie.coord.HCatELFunctions#ph3_coord_dataInPartitions,
        coord:dataOutPartitions=org.apache.oozie.coord.HCatELFunctions#ph3_coord_dataOutPartitions,
        coord:dataOutPartitionValue=org.apache.oozie.coord.HCatELFunctions#ph3_coord_dataOutPartitionValue,
        hadoop:conf=org.apache.oozie.action.hadoop.HadoopELFunctions#hadoop_conf
    </value>
    <description>
        EL functions declarations, separated by commas, format is [PREFIX:]NAME=CLASS#METHOD.
    </description>
</property>

几个具体实现

coord:databaseIn=org.apache.oozie.coord.HCatELFunctions#ph3_coord_databaseIn

public static String ph3_coord_databaseIn(String dataName) {
    HCatURI hcatURI = getURIFromResolved(dataName, EventType.input);
    if (hcatURI != null) {
        return hcatURI.getDb();
    }
    else {
        return "";
    }
}


coord:databaseOut=org.apache.oozie.coord.HCatELFunctions#ph3_coord_databaseOut


public static String ph3_coord_databaseOut(String dataName) {
    HCatURI hcatURI = getURIFromResolved(dataName, EventType.output);
    if (hcatURI != null) {
        return hcatURI.getDb();
    }
    else {
        return "";
    }
}



private static HCatURI getURIFromResolved(String dataInName, EventType type) {
    final XLog LOG = XLog.getLog(HCatELFunctions.class);
    StringBuilder uriTemplate = new StringBuilder();
    ELEvaluator eval = ELEvaluator.getCurrent();
    String uris;
    if(type == EventType.input) {
        uris = (String) eval.getVariable(".datain." + dataInName);
    }
    else { //type=output
        uris = (String) eval.getVariable(".dataout." + dataInName);
    }
    if (uris != null) {
        String[] uri = uris.split(CoordELFunctions.DIR_SEPARATOR, -1);
        uriTemplate.append(uri[0]);
    }
    else {
        LOG.warn("URI is NULL");
        return null;
    }
    LOG.info("uriTemplate [{0}] ", uriTemplate);
    HCatURI hcatURI;
    try {
        hcatURI = new HCatURI(uriTemplate.toString());
    }
    catch (URISyntaxException e) {
        LOG.info("uriTemplate [{0}]. Reason [{1}]: ", uriTemplate, e);
        throw new RuntimeException("HCat URI can't be parsed " + e);
    }
    return hcatURI;
}

这里并没有把所以的表达式都列全,但是大家应该可以了解了表达的计算模式,还有一点可能大家需要清除的,就是在实现方法中 有 ph1/ph2/ph3这样的标识,在ph1阶段可能仅仅是 把需要处理的数据放入上下文,在ph2或者ph3才会 真正计算出值,因为ph3、ph2的时候是action真正启动,实例的时候。

Oozie使用这些key 创建不同的 evaluator 从而到达 隔离的效果;

这里列举了不同的表达式,但是oozie在什么时候使用到他们的呢:
evaluator.evaluate

比如在 ActionStartXCommand 中:

String tmpActionConf = XmlUtils.removeComments(wfAction.getConf());
String actionConf = context.getELEvaluator().evaluate(tmpActionConf, String.class);

这样就可以将 actionConf 中所以的需要处理的表达式都处理了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,671评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,442评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,524评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,623评论 1 275
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,642评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,584评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,953评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,621评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,865评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,608评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,698评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,378评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,958评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,940评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,173评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,419评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,425评论 2 342

推荐阅读更多精彩内容