eu.stratosphere.nephele.jobmanager.web.JobmanagerInfoServlet.java Source code

Java tutorial

Introduction

Here is the source code for eu.stratosphere.nephele.jobmanager.web.JobmanagerInfoServlet.java

Source

/***********************************************************************************************************************
 * Copyright (C) 2010-2013 by the Stratosphere project (http://stratosphere.eu)
 *
 * Licensed 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 eu.stratosphere.nephele.jobmanager.web;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.jetty.io.EofException;

import eu.stratosphere.api.common.accumulators.AccumulatorHelper;
import eu.stratosphere.nephele.event.job.AbstractEvent;
import eu.stratosphere.nephele.event.job.ExecutionStateChangeEvent;
import eu.stratosphere.nephele.event.job.JobEvent;
import eu.stratosphere.nephele.event.job.RecentJobEvent;
import eu.stratosphere.nephele.execution.ExecutionState;
import eu.stratosphere.nephele.jobgraph.JobID;
import eu.stratosphere.nephele.jobgraph.JobStatus;
import eu.stratosphere.nephele.jobmanager.JobManager;
import eu.stratosphere.nephele.managementgraph.ManagementGraph;
import eu.stratosphere.nephele.managementgraph.ManagementGraphIterator;
import eu.stratosphere.nephele.managementgraph.ManagementGroupVertex;
import eu.stratosphere.nephele.managementgraph.ManagementGroupVertexID;
import eu.stratosphere.nephele.managementgraph.ManagementVertex;
import eu.stratosphere.nephele.services.accumulators.AccumulatorEvent;
import eu.stratosphere.util.StringUtils;

public class JobmanagerInfoServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

    /**
     * The log for this class.
     */
    private static final Log LOG = LogFactory.getLog(JobmanagerInfoServlet.class);

    /**
     * Underlying JobManager
     */
    private final JobManager jobmanager;

    public JobmanagerInfoServlet(JobManager jobmanager) {
        this.jobmanager = jobmanager;
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        resp.setStatus(HttpServletResponse.SC_OK);
        resp.setContentType("application/json");

        try {
            if ("archive".equals(req.getParameter("get"))) {
                writeJsonForArchive(resp.getWriter(), jobmanager.getOldJobs());
            } else if ("job".equals(req.getParameter("get"))) {
                String jobId = req.getParameter("job");
                writeJsonForArchivedJob(resp.getWriter(),
                        jobmanager.getArchive().getJob(JobID.fromHexString(jobId)));
            } else if ("groupvertex".equals(req.getParameter("get"))) {
                String jobId = req.getParameter("job");
                String groupvertexId = req.getParameter("groupvertex");
                writeJsonForArchivedJobGroupvertex(resp.getWriter(),
                        jobmanager.getArchive().getJob(JobID.fromHexString(jobId)),
                        ManagementGroupVertexID.fromHexString(groupvertexId));
            } else if ("taskmanagers".equals(req.getParameter("get"))) {
                resp.getWriter().write("{\"taskmanagers\": " + jobmanager.getNumberOfTaskTrackers() + "}");
            } else if ("cancel".equals(req.getParameter("get"))) {
                String jobId = req.getParameter("job");
                jobmanager.cancelJob(JobID.fromHexString(jobId));
            } else if ("updates".equals(req.getParameter("get"))) {
                String jobId = req.getParameter("job");
                writeJsonUpdatesForJob(resp.getWriter(), JobID.fromHexString(jobId));
            } else {
                writeJsonForJobs(resp.getWriter(), jobmanager.getRecentJobs());
            }

        } catch (Exception e) {
            resp.setStatus(HttpServletResponse.SC_BAD_REQUEST);
            resp.getWriter().print(e.getMessage());
            if (LOG.isWarnEnabled()) {
                LOG.warn(StringUtils.stringifyException(e));
            }
        }
    }

    /**
     * Writes ManagementGraph as Json for all recent jobs
     * 
     * @param wrt
     * @param jobs
     */
    private void writeJsonForJobs(PrintWriter wrt, List<RecentJobEvent> jobs) {

        try {

            wrt.write("[");

            // Loop Jobs
            for (int i = 0; i < jobs.size(); i++) {
                RecentJobEvent jobEvent = jobs.get(i);

                writeJsonForJob(wrt, jobEvent);

                //Write seperator between json objects
                if (i != jobs.size() - 1) {
                    wrt.write(",");
                }
            }
            wrt.write("]");

        } catch (EofException eof) { // Connection closed by client
            LOG.info("Info server for jobmanager: Connection closed by client, EofException");
        } catch (IOException ioe) { // Connection closed by client   
            LOG.info("Info server for jobmanager: Connection closed by client, IOException");
        }

    }

    private void writeJsonForJob(PrintWriter wrt, RecentJobEvent jobEvent) throws IOException {

        ManagementGraph jobManagementGraph = jobmanager.getManagementGraph(jobEvent.getJobID());

        //Serialize job to json
        wrt.write("{");
        wrt.write("\"jobid\": \"" + jobEvent.getJobID() + "\",");
        wrt.write("\"jobname\": \"" + jobEvent.getJobName() + "\",");
        wrt.write("\"status\": \"" + jobEvent.getJobStatus() + "\",");
        wrt.write("\"time\": " + jobEvent.getTimestamp() + ",");

        // Serialize ManagementGraph to json
        wrt.write("\"groupvertices\": [");
        boolean first = true;
        for (ManagementGroupVertex groupVertex : jobManagementGraph.getGroupVerticesInTopologicalOrder()) {
            //Write seperator between json objects
            if (first) {
                first = false;
            } else {
                wrt.write(",");
            }

            wrt.write(groupVertex.toJson());
        }
        wrt.write("]");
        wrt.write("}");

    }

    /**
     * Writes Json with a list of currently archived jobs, sorted by time
     * 
     * @param wrt
     * @param jobs
     */
    private void writeJsonForArchive(PrintWriter wrt, List<RecentJobEvent> jobs) {

        wrt.write("[");

        // sort jobs by time
        Collections.sort(jobs, new Comparator<RecentJobEvent>() {
            @Override
            public int compare(RecentJobEvent o1, RecentJobEvent o2) {
                if (o1.getTimestamp() < o2.getTimestamp()) {
                    return 1;
                } else {
                    return -1;
                }
            }

        });

        // Loop Jobs
        for (int i = 0; i < jobs.size(); i++) {
            RecentJobEvent jobEvent = jobs.get(i);

            //Serialize job to json
            wrt.write("{");
            wrt.write("\"jobid\": \"" + jobEvent.getJobID() + "\",");
            wrt.write("\"jobname\": \"" + jobEvent.getJobName() + "\",");
            wrt.write("\"status\": \"" + jobEvent.getJobStatus() + "\",");
            wrt.write("\"time\": " + jobEvent.getTimestamp());

            wrt.write("}");

            //Write seperator between json objects
            if (i != jobs.size() - 1) {
                wrt.write(",");
            }
        }
        wrt.write("]");

    }

    /**
     * Writes infos about archived job in Json format, including groupvertices and groupverticetimes
     * 
     * @param wrt
     * @param jobEvent
     */
    private void writeJsonForArchivedJob(PrintWriter wrt, RecentJobEvent jobEvent) {

        try {

            wrt.write("[");

            ManagementGraph jobManagementGraph = jobmanager.getManagementGraph(jobEvent.getJobID());

            //Serialize job to json
            wrt.write("{");
            wrt.write("\"jobid\": \"" + jobEvent.getJobID() + "\",");
            wrt.write("\"jobname\": \"" + jobEvent.getJobName() + "\",");
            wrt.write("\"status\": \"" + jobEvent.getJobStatus() + "\",");
            wrt.write("\"SCHEDULED\": "
                    + jobmanager.getArchive().getJobTime(jobEvent.getJobID(), JobStatus.SCHEDULED) + ",");
            wrt.write("\"RUNNING\": " + jobmanager.getArchive().getJobTime(jobEvent.getJobID(), JobStatus.RUNNING)
                    + ",");
            wrt.write("\"FINISHED\": " + jobmanager.getArchive().getJobTime(jobEvent.getJobID(), JobStatus.FINISHED)
                    + ",");
            wrt.write("\"FAILED\": " + jobmanager.getArchive().getJobTime(jobEvent.getJobID(), JobStatus.FAILED)
                    + ",");
            wrt.write("\"CANCELED\": " + jobmanager.getArchive().getJobTime(jobEvent.getJobID(), JobStatus.CANCELED)
                    + ",");
            wrt.write("\"CREATED\": " + jobmanager.getArchive().getJobTime(jobEvent.getJobID(), JobStatus.CREATED)
                    + ",");

            if (jobEvent.getJobStatus() == JobStatus.FAILED) {
                ManagementGraphIterator managementGraphIterator = new ManagementGraphIterator(jobManagementGraph,
                        true);
                wrt.write("\"failednodes\": [");
                HashSet<String> map = new HashSet<String>();
                boolean first = true;
                while (managementGraphIterator.hasNext()) {
                    ManagementVertex managementVertex = managementGraphIterator.next();
                    String instanceName = managementVertex.getInstanceName();
                    if (managementVertex.getExecutionState() == ExecutionState.FAILED
                            && !map.contains(instanceName)) {
                        if (first) {
                            first = false;
                        } else {
                            wrt.write(",");
                        }
                        wrt.write("{");
                        wrt.write("\"node\": \"" + instanceName + "\",");
                        wrt.write("\"message\": \"" + StringUtils.escapeHtml(managementVertex.getOptMessage())
                                + "\"");
                        wrt.write("}");
                        map.add(instanceName);
                    }
                }
                wrt.write("],");
            }

            // Serialize ManagementGraph to json
            wrt.write("\"groupvertices\": [");
            boolean first = true;
            for (ManagementGroupVertex groupVertex : jobManagementGraph.getGroupVerticesInTopologicalOrder()) {
                //Write seperator between json objects
                if (first) {
                    first = false;
                } else {
                    wrt.write(",");
                }

                wrt.write(groupVertex.toJson());

            }
            wrt.write("],");

            // write accumulators
            AccumulatorEvent accumulators = jobmanager.getAccumulatorResults(jobEvent.getJobID());
            Map<String, Object> accMap = AccumulatorHelper.toResultMap(accumulators.getAccumulators());

            wrt.write("\n\"accumulators\": [");
            int i = 0;
            for (Entry<String, Object> accumulator : accMap.entrySet()) {
                wrt.write(
                        "{ \"name\": \"" + accumulator.getKey() + " (" + accumulator.getValue().getClass().getName()
                                + ")\"," + " \"value\": \"" + accumulator.getValue().toString() + "\"}\n");
                if (++i < accMap.size()) {
                    wrt.write(",");
                }
            }
            wrt.write("],\n");

            wrt.write("\"groupverticetimes\": {");
            first = true;
            for (ManagementGroupVertex groupVertex : jobManagementGraph.getGroupVerticesInTopologicalOrder()) {

                if (first) {
                    first = false;
                } else {
                    wrt.write(",");
                }

                // Calculate start and end time for groupvertex
                long started = Long.MAX_VALUE;
                long ended = 0;

                // Take earliest running state and latest endstate of groupmembers
                for (int j = 0; j < groupVertex.getNumberOfGroupMembers(); j++) {
                    ManagementVertex vertex = groupVertex.getGroupMember(j);

                    long running = jobmanager.getArchive().getVertexTime(jobEvent.getJobID(), vertex.getID(),
                            ExecutionState.RUNNING);
                    if (running != 0 && running < started) {
                        started = running;
                    }

                    long finished = jobmanager.getArchive().getVertexTime(jobEvent.getJobID(), vertex.getID(),
                            ExecutionState.FINISHED);
                    long canceled = jobmanager.getArchive().getVertexTime(jobEvent.getJobID(), vertex.getID(),
                            ExecutionState.CANCELED);
                    long failed = jobmanager.getArchive().getVertexTime(jobEvent.getJobID(), vertex.getID(),
                            ExecutionState.FAILED);

                    if (finished != 0 && finished > ended) {
                        ended = finished;
                    }

                    if (canceled != 0 && canceled > ended) {
                        ended = canceled;
                    }

                    if (failed != 0 && failed > ended) {
                        ended = failed;
                    }

                }

                wrt.write("\"" + groupVertex.getID() + "\": {");
                wrt.write("\"groupvertexid\": \"" + groupVertex.getID() + "\",");
                wrt.write("\"groupvertexname\": \"" + groupVertex + "\",");
                wrt.write("\"STARTED\": " + started + ",");
                wrt.write("\"ENDED\": " + ended);
                wrt.write("}");

            }

            wrt.write("}");

            wrt.write("}");

            wrt.write("]");

        } catch (EofException eof) { // Connection closed by client
            LOG.info("Info server for jobmanager: Connection closed by client, EofException");
        } catch (IOException ioe) { // Connection closed by client   
            LOG.info("Info server for jobmanager: Connection closed by client, IOException");
        }

    }

    /**
     * Writes all updates (events) for a given job since a given time
     * 
     * @param wrt
     * @param jobId
     */
    private void writeJsonUpdatesForJob(PrintWriter wrt, JobID jobId) {

        try {

            List<AbstractEvent> events = jobmanager.getEvents(jobId);

            //Serialize job to json
            wrt.write("{");
            wrt.write("\"jobid\": \"" + jobId + "\",");
            wrt.write("\"timestamp\": \"" + System.currentTimeMillis() + "\",");
            wrt.write("\"recentjobs\": [");

            boolean first = true;
            for (RecentJobEvent rje : jobmanager.getRecentJobs()) {
                if (first) {
                    first = false;
                } else {
                    wrt.write(",");
                }

                wrt.write("\"" + rje.getJobID().toString() + "\"");
            }

            wrt.write("],");

            wrt.write("\"vertexevents\": [");

            first = true;
            for (AbstractEvent event : events) {

                if (event instanceof ExecutionStateChangeEvent) {

                    if (first) {
                        first = false;
                    } else {
                        wrt.write(",");
                    }

                    ExecutionStateChangeEvent vertexevent = (ExecutionStateChangeEvent) event;
                    wrt.write("{");
                    wrt.write("\"vertexid\": \"" + vertexevent.getVertexID() + "\",");
                    wrt.write("\"newstate\": \"" + vertexevent.getNewExecutionState() + "\",");
                    wrt.write("\"timestamp\": \"" + vertexevent.getTimestamp() + "\"");
                    wrt.write("}");
                }
            }

            wrt.write("],");

            wrt.write("\"jobevents\": [");

            first = true;
            for (AbstractEvent event : events) {

                if (event instanceof JobEvent) {

                    if (first) {
                        first = false;
                    } else {
                        wrt.write(",");
                    }

                    JobEvent jobevent = (JobEvent) event;
                    wrt.write("{");
                    wrt.write("\"newstate\": \"" + jobevent.getCurrentJobStatus() + "\",");
                    wrt.write("\"timestamp\": \"" + jobevent.getTimestamp() + "\"");
                    wrt.write("}");
                }
            }

            wrt.write("]");

            wrt.write("}");

        } catch (EofException eof) { // Connection closed by client
            LOG.info("Info server for jobmanager: Connection closed by client, EofException");
        } catch (IOException ioe) { // Connection closed by client   
            LOG.info("Info server for jobmanager: Connection closed by client, IOException");
        }

    }

    /**
     * Writes infos about one particular archived groupvertex in a job, including all groupmembers, their times and status
     * 
     * @param wrt
     * @param jobEvent
     * @param groupvertexId
     */
    private void writeJsonForArchivedJobGroupvertex(PrintWriter wrt, RecentJobEvent jobEvent,
            ManagementGroupVertexID groupvertexId) {

        try {

            ManagementGraph jobManagementGraph = jobmanager.getManagementGraph(jobEvent.getJobID());

            ManagementGroupVertex groupvertex = jobManagementGraph.getGroupVertexByID(groupvertexId);

            // Serialize ManagementGraph to json
            wrt.write("{\"groupvertex\": " + groupvertex.toJson() + ",");

            wrt.write("\"verticetimes\": {");
            boolean first = true;
            for (ManagementGroupVertex groupVertex : jobManagementGraph.getGroupVerticesInTopologicalOrder()) {

                for (int j = 0; j < groupVertex.getNumberOfGroupMembers(); j++) {
                    ManagementVertex vertex = groupVertex.getGroupMember(j);

                    if (first) {
                        first = false;
                    } else {
                        wrt.write(",");
                    }

                    wrt.write("\"" + vertex.getID() + "\": {");
                    wrt.write("\"vertexid\": \"" + vertex.getID() + "\",");
                    wrt.write("\"vertexname\": \"" + vertex + "\",");
                    wrt.write("\"CREATED\": " + jobmanager.getArchive().getVertexTime(jobEvent.getJobID(),
                            vertex.getID(), ExecutionState.CREATED) + ",");
                    wrt.write("\"SCHEDULED\": " + jobmanager.getArchive().getVertexTime(jobEvent.getJobID(),
                            vertex.getID(), ExecutionState.SCHEDULED) + ",");
                    wrt.write("\"ASSIGNED\": " + jobmanager.getArchive().getVertexTime(jobEvent.getJobID(),
                            vertex.getID(), ExecutionState.ASSIGNED) + ",");
                    wrt.write("\"READY\": " + jobmanager.getArchive().getVertexTime(jobEvent.getJobID(),
                            vertex.getID(), ExecutionState.READY) + ",");
                    wrt.write("\"STARTING\": " + jobmanager.getArchive().getVertexTime(jobEvent.getJobID(),
                            vertex.getID(), ExecutionState.STARTING) + ",");
                    wrt.write("\"RUNNING\": " + jobmanager.getArchive().getVertexTime(jobEvent.getJobID(),
                            vertex.getID(), ExecutionState.RUNNING) + ",");
                    wrt.write("\"FINISHING\": " + jobmanager.getArchive().getVertexTime(jobEvent.getJobID(),
                            vertex.getID(), ExecutionState.FINISHING) + ",");
                    wrt.write("\"FINISHED\": " + jobmanager.getArchive().getVertexTime(jobEvent.getJobID(),
                            vertex.getID(), ExecutionState.FINISHED) + ",");
                    wrt.write("\"CANCELING\": " + jobmanager.getArchive().getVertexTime(jobEvent.getJobID(),
                            vertex.getID(), ExecutionState.CANCELING) + ",");
                    wrt.write("\"CANCELED\": " + jobmanager.getArchive().getVertexTime(jobEvent.getJobID(),
                            vertex.getID(), ExecutionState.CANCELED) + ",");
                    wrt.write("\"FAILED\": " + jobmanager.getArchive().getVertexTime(jobEvent.getJobID(),
                            vertex.getID(), ExecutionState.FAILED) + "");
                    wrt.write("}");
                }

            }
            wrt.write("}}");

        } catch (EofException eof) { // Connection closed by client
            LOG.info("Info server for jobmanager: Connection closed by client, EofException");
        } catch (IOException ioe) { // Connection closed by client   
            LOG.info("Info server for jobmanager: Connection closed by client, IOException");
        }

    }
}