com.aliyun.odps.mapred.bridge.BridgeRunningJob.java Source code

Java tutorial

Introduction

Here is the source code for com.aliyun.odps.mapred.bridge.BridgeRunningJob.java

Source

/*
 * 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 com.aliyun.odps.mapred.bridge;

import java.io.IOException;
import java.io.PrintStream;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;

import com.alibaba.fastjson.JSON;
import com.aliyun.odps.Instance;
import com.aliyun.odps.Instance.StageProgress;
import com.aliyun.odps.Instance.Status;
import com.aliyun.odps.Instance.TaskStatus;
import com.aliyun.odps.Instance.TaskSummary;
import com.aliyun.odps.OdpsException;
import com.aliyun.odps.commons.util.CostResultParser;
import com.aliyun.odps.counter.CounterGroup;
import com.aliyun.odps.counter.Counters;
import com.aliyun.odps.mapred.EventListener;
import com.aliyun.odps.mapred.JobStatus;
import com.aliyun.odps.mapred.RunningJob;
import com.aliyun.odps.mapred.conf.SessionState;
import com.aliyun.odps.udf.utils.CounterUtils;

public class BridgeRunningJob implements RunningJob {

    protected Instance instance;
    protected JobStatus state = JobStatus.PREP;
    protected Counters counters = new Counters();
    protected String diagnostics = "";
    protected boolean stopped = false;

    private long timeMark = 0;
    private boolean hasPrintSummary = false;
    private boolean hasPrintResult = false;

    private float mapProgress = 0;
    private float reduceProgress = 0;

    private final String taskName;
    private EventListener event = null;

    private boolean isCountersOk = true;
    private boolean isCostMode = false;

    public BridgeRunningJob(Instance instance, String taskName, EventListener event) {
        this.instance = instance;
        this.taskName = taskName;
        this.event = event;

        // print logview url to stdout
        startUp();
    }

    @Override
    public String getInstanceID() {
        return instance.getId();
    }

    @Override
    public boolean isComplete() {
        if (isFinished()) {
            return true;
        }
        updateStatus();
        return isFinished();
    }

    @Override
    public boolean isSuccessful() {
        if (isFinished()) {
            return (state == JobStatus.SUCCEEDED);
        }
        updateStatus();
        return (state == JobStatus.SUCCEEDED);
    }

    @Override
    public void waitForCompletion() {
        int sleeptime = 1000;

        while (!isComplete()) {
            try {
                Thread.sleep(sleeptime);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            sleeptime = ((sleeptime + 500) > 4000) ? 4000 : sleeptime + 500;
        }
        // Clean
        event.onComplete();
    }

    private void startUp() {
        try {
            String log = SessionState.get().getOdps().logview().generateLogView(instance, 7 * 24);
            System.out.println(log);
        } catch (Exception e) {
            // do nothing if not load logview class
        }
    }

    @Override
    public JobStatus getJobStatus() {
        if (isFinished()) {
            return state;
        }
        updateStatus();
        return state;
    }

    @Override
    public void killJob() {
        stopped = true;
        try {
            instance.stop();
        } catch (OdpsException ex) {
            throw new RuntimeException("Kill job Failed", ex);
        }
        // Clean
        event.onComplete();
    }

    @Override
    public Counters getCounters() {
        if (!isCountersOk) {
            throw new RuntimeException("Get Counters Failed!");
        }
        return counters;
    }

    @Override
    public String getDiagnostics() {
        return diagnostics;
    }

    protected boolean isFinished() {
        return (state == JobStatus.FAILED) || (state == JobStatus.SUCCEEDED) || (state == JobStatus.KILLED);
    }

    protected void updateStatus() {
        try {
            Status instanceStatus = instance.getStatus();
            if (instanceStatus == Status.RUNNING || instanceStatus == Status.SUSPENDED) {
                state = JobStatus.RUNNING;
            } else if (instanceStatus == Status.TERMINATED) {
                TaskStatus taskStatus = instance.getTaskStatus().values().iterator().next();
                switch (taskStatus.getStatus()) {
                case WAITING:
                case RUNNING:
                case FAILED:
                    state = JobStatus.FAILED;
                    break;
                case SUCCESS:
                    state = JobStatus.SUCCEEDED;
                    break;
                case CANCELLED:
                    state = JobStatus.KILLED;
                    break;
                default:
                    throw new OdpsException("Got Unknown task status: " + taskStatus.getStatus());
                }
            } else {
                throw new OdpsException("Got unknown instance status '" + instanceStatus + "'");
            }

            // try to print process information
            if (needPrintProcess() || isFinished()) {
                printProgress();
            }
        } catch (OdpsException ex) {
            throw new RuntimeException(ex);
        }

        if (isFinished()) {
            try {
                printSummaryAndCollectCounters();
                printResult();
            } catch (Exception ex) {
                isCountersOk = false;
                System.out.println("Get summary failed.");
            }
        }

    }

    private boolean needPrintProcess() {
        long now = System.currentTimeMillis();
        long interval = 5 * 1000;
        if (now - timeMark > interval) {
            timeMark = now;
            return true;
        }
        return false;
    }

    /**
     * Print job progress.
     *
     * @throws IOException
     * @throws OdpsException
     *     if get task progress failed
     */
    private void printProgress() throws OdpsException {
        PrintStream out = System.out;

        List<StageProgress> stages = null;
        stages = instance.getTaskProgress(taskName);

        if (stages != null && stages.size() != 0) {

            out.print(Instance.getStageProgressFormattedString(stages));

            int mappers = 0;
            int reducers = 0;
            mapProgress = 0;
            reduceProgress = 0;
            for (StageProgress stage : stages) {
                int totalWorkers = stage.getTotalWorkers();
                if (stage.getName().startsWith("M")) {
                    mappers += totalWorkers;
                    mapProgress += stage.getFinishedPercentage() / 100.0 * totalWorkers;
                } else {
                    reducers += totalWorkers;
                    reduceProgress += stage.getFinishedPercentage() / 100.0 * totalWorkers;
                }
            }
            mapProgress = mappers == 0 ? 0 : mapProgress / mappers;
            reduceProgress = reducers == 0 ? 0 : reduceProgress / reducers;
        } else {
            out.print("...");
        }
        out.print('\r');
        out.flush();
    }

    @SuppressWarnings({ "rawtypes" })
    private void printSummaryAndCollectCounters() throws IOException {
        if (hasPrintSummary || !isSuccessful()) {
            return;
        }

        TaskSummary taskSummary = null;
        try {
            taskSummary = instance.getTaskSummary(taskName);
        } catch (OdpsException ex) {
            throw new IOException("Get summary encounter error: ", ex);
        }

        if (taskSummary == null) {
            if (System.getProperty("omit.taskstatus.failure", "false").equalsIgnoreCase("true")) {
                System.out.println("No summary in place.");
                return;
            } else {
                throw new IOException("No summary in place.");
            }
        }

        Map tasks = (Map) taskSummary.get("Stages");
        Counters tmpCounters;
        for (Object e : tasks.values()) {
            Map task = (Map) e;
            Map countersValue = (Map) task.get("UserCounters");
            if (countersValue != null) {
                tmpCounters = CounterUtils.createFromJsonString(JSON.toJSONString(countersValue));
                Iterator<CounterGroup> iter = tmpCounters.iterator();
                while (iter.hasNext()) {
                    if (iter.next().getName().equals("ODPS_SDK_FRAMEWORK_COUNTER_GROUP")) {
                        // ignore framework counter group
                        iter.remove();
                    }
                }
                counters.incrAllCounters(tmpCounters);
            }
        }
        System.out.println(taskSummary.getSummaryText());
        System.out.println(counters);
        hasPrintSummary = true;
    }

    private void printResult() throws IOException {
        if (!hasPrintResult) {
            try {
                Map<String, String> m = instance.getTaskResults();
                diagnostics = m.values().iterator().next();

                if (state == JobStatus.SUCCEEDED) {
                    if (!StringUtils.isEmpty(diagnostics)) {
                        if (isCostMode) {
                            diagnostics = CostResultParser.parse(diagnostics, "MapReduce");
                        }
                        System.err.println(diagnostics);
                    }
                    System.err.println("OK");
                } else {
                    if (!StringUtils.isEmpty(diagnostics)) {
                        System.err.println("FAILED: " + diagnostics);
                    } else {
                        System.err.println("ERROR: " + state.toString());
                    }
                }

                hasPrintResult = true;
            } catch (Exception ex) {
                throw new IOException("Get result encounter error: " + ex.getMessage());
            }
        }
    }

    @Override
    public float mapProgress() throws IOException {
        if (isSuccessful()) {
            return 1f;
        }
        return this.mapProgress;
    }

    @Override
    public float reduceProgress() throws IOException {
        if (isSuccessful()) {
            return 1f;
        }
        return this.reduceProgress;
    }

    public boolean isCostMode() {
        return isCostMode;
    }

    public void setIsCostMode(boolean isCostMode) {
        this.isCostMode = isCostMode;
    }

}