org.apache.hadoop.mapred.MockSimulatorJobTracker.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.hadoop.mapred.MockSimulatorJobTracker.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 org.apache.hadoop.mapred;

import java.io.IOException;
import java.util.SortedMap;
import java.util.TreeMap;

import junit.framework.Assert;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.hadoop.mapred.TaskStatus.State;
import org.apache.hadoop.mapred.TaskStatus.Phase;
import org.apache.hadoop.mapreduce.ClusterMetrics;
import org.apache.hadoop.mapreduce.Counters;
import org.apache.hadoop.mapreduce.JobID;
import org.apache.hadoop.mapreduce.JobPriority;
import org.apache.hadoop.mapreduce.JobStatus;
import org.apache.hadoop.mapreduce.QueueAclsInfo;
import org.apache.hadoop.mapreduce.QueueInfo;
import org.apache.hadoop.mapreduce.TaskAttemptID;
import org.apache.hadoop.mapreduce.TaskReport;
import org.apache.hadoop.mapreduce.TaskTrackerInfo;
import org.apache.hadoop.mapreduce.TaskType;
import org.apache.hadoop.mapreduce.protocol.ClientProtocol;
import org.apache.hadoop.tools.rumen.TaskInfo;
import org.apache.hadoop.tools.rumen.MapTaskAttemptInfo;
import org.apache.hadoop.tools.rumen.ReduceTaskAttemptInfo;

//
// Mock jobtracker class that check heartbeat() in parameters and 
// sends responses based on a prepopulated table
//  
public class MockSimulatorJobTracker implements InterTrackerProtocol, ClientProtocol {
    private final long simulationStartTime;
    private final int heartbeatInterval;

    // Helper table, used iff checkHeartbeats == true
    // Contains the expected task tracker status report at time t for all task 
    // trackers identified by their name and the heartbeat response to send
    private SortedMap<Long, TreeMap<String, HeartbeatHelper>> heartbeats = new TreeMap<Long, TreeMap<String, HeartbeatHelper>>();
    private final boolean checkHeartbeats;
    private int jobId = 0;

    static final Log LOG = LogFactory.getLog(MockSimulatorJobTracker.class);

    public MockSimulatorJobTracker(long simulationStartTime, int heartbeatInterval, boolean checkHeartbeats) {
        this.simulationStartTime = simulationStartTime;
        this.heartbeatInterval = heartbeatInterval;
        this.checkHeartbeats = checkHeartbeats;
    }

    @Override
    public JobID getNewJobID() throws IOException {
        return new JobID("mockJT", jobId++);
    }

    @Override
    public JobStatus submitJob(JobID jobId) throws IOException {
        JobStatus status = new JobStatus(jobId, 0.0f, 0.0f, 0.0f, 0.0f, JobStatus.State.RUNNING, JobPriority.NORMAL,
                "", "", "", "");
        return status;
    }

    @Override
    public HeartbeatResponse heartbeat(TaskTrackerStatus status, boolean restarted, boolean initialContact,
            boolean acceptNewTasks, short responseId) throws IOException {
        if (!(status instanceof SimulatorTaskTrackerStatus)) {
            throw new IllegalArgumentException(
                    "Expecting SimulatorTaskTrackerStatus, actual status type " + status.getClass());
        }
        SimulatorTaskTrackerStatus trackerStatus = (SimulatorTaskTrackerStatus) status;
        long now = trackerStatus.getCurrentSimulationTime();
        String trackerName = status.getTrackerName();

        LOG.debug("Received heartbeat() from trackerName=" + trackerName + ", now=" + now);

        HeartbeatResponse response = new HeartbeatResponse();
        response.setHeartbeatInterval(heartbeatInterval);
        response.setActions(new TaskTrackerAction[0]);

        if (checkHeartbeats) {
            Assert.assertFalse("No more heartbeats were expected ", heartbeats.isEmpty());
            long nextToCheck = heartbeats.firstKey();
            // Missing heartbeat check
            Assert.assertTrue(nextToCheck <= now);
            if (nextToCheck < now) {
                LOG.debug("Simulation time progressed, last checked heartbeat at=" + nextToCheck + ", now=" + now
                        + ". Checking if no " + "required heartbeats were missed in the past");
                SortedMap<String, HeartbeatHelper> previousHeartbeats = heartbeats.get(nextToCheck);
                Assert.assertNotNull(previousHeartbeats);
                Assert.assertTrue(previousHeartbeats.isEmpty());
                heartbeats.remove(nextToCheck);
                nextToCheck = heartbeats.firstKey();
            }
            Assert.assertEquals("Heartbeat at the wrong time", nextToCheck, now);

            SortedMap<String, HeartbeatHelper> currentHeartbeats = heartbeats.get(now);
            HeartbeatHelper currentHeartbeat = currentHeartbeats.get(trackerName);
            Assert.assertNotNull("Unknown task tracker name=" + trackerName, currentHeartbeat);
            currentHeartbeats.remove(trackerName);

            currentHeartbeat.checkHeartbeatParameters(status, acceptNewTasks);

            response.setActions(currentHeartbeat.getTaskTrackerActions());
        }
        return response;
    }

    //
    // Populates the mock jobtracker's helper & checker table with expected
    // empty reports from the task trackers and empty task actions to perform
    // 
    public void expectEmptyHeartbeats(String taskTrackerName, int numHeartbeats) {
        long simulationTime = simulationStartTime;
        for (int i = 0; i < numHeartbeats; i++) {
            TreeMap<String, HeartbeatHelper> hb = heartbeats.get(simulationTime);
            if (hb == null) {
                hb = new TreeMap<String, HeartbeatHelper>();
                heartbeats.put(simulationTime, hb);
            }
            hb.put(taskTrackerName, new HeartbeatHelper());
            simulationTime += heartbeatInterval;
        }
    }

    // Fills in all the expected and return heartbeat parameters corresponding
    // to running a map task on a task tracker.
    // Use killTime < 0 if not killed
    public void runMapTask(String taskTrackerName, TaskAttemptID taskId, long mapStart, long mapRuntime,
            long killHeartbeat) {
        long mapDone = mapStart + mapRuntime;
        long mapEndHeartbeat = nextHeartbeat(mapDone);
        final boolean isKilled = (killHeartbeat >= 0);
        if (isKilled) {
            mapEndHeartbeat = nextHeartbeat(killHeartbeat + 1);
        }

        LOG.debug("mapStart=" + mapStart + ", mapDone=" + mapDone + ", mapEndHeartbeat=" + mapEndHeartbeat
                + ", killHeartbeat=" + killHeartbeat);

        final int numSlotsRequired = 1;
        org.apache.hadoop.mapred.TaskAttemptID taskIdOldApi = org.apache.hadoop.mapred.TaskAttemptID
                .downgrade(taskId);
        Task task = new MapTask("dummyjobfile", taskIdOldApi, 0, "dummysplitclass", null, numSlotsRequired);
        // all byte counters are 0
        TaskInfo taskInfo = new TaskInfo(0, 0, 0, 0, 0);
        MapTaskAttemptInfo taskAttemptInfo = new MapTaskAttemptInfo(State.SUCCEEDED, taskInfo, mapRuntime);
        TaskTrackerAction action = new SimulatorLaunchTaskAction(task, taskAttemptInfo);
        heartbeats.get(mapStart).get(taskTrackerName).addTaskTrackerAction(action);
        if (isKilled) {
            action = new KillTaskAction(taskIdOldApi);
            heartbeats.get(killHeartbeat).get(taskTrackerName).addTaskTrackerAction(action);
        }

        for (long simulationTime = mapStart
                + heartbeatInterval; simulationTime <= mapEndHeartbeat; simulationTime += heartbeatInterval) {
            State state = simulationTime < mapEndHeartbeat ? State.RUNNING : State.SUCCEEDED;
            if (simulationTime == mapEndHeartbeat && isKilled) {
                state = State.KILLED;
            }
            MapTaskStatus mapStatus = new MapTaskStatus(task.getTaskID(), 0.0f, 0, state, "", "", null, Phase.MAP,
                    null);
            heartbeats.get(simulationTime).get(taskTrackerName).addTaskReport(mapStatus);
        }
    }

    // Fills in all the expected and return heartbeat parameters corresponding
    // to running a reduce task on a task tracker.
    // Use killTime<0 if not killed
    public void runReduceTask(String taskTrackerName, TaskAttemptID taskId, long reduceStart, long mapDoneDelay,
            long reduceRuntime, long killHeartbeat) {
        long mapDone = nextHeartbeat(reduceStart + mapDoneDelay);
        long reduceDone = mapDone + reduceRuntime;
        long reduceEndHeartbeat = nextHeartbeat(reduceDone);
        final boolean isKilled = (killHeartbeat >= 0);
        if (isKilled) {
            reduceEndHeartbeat = nextHeartbeat(killHeartbeat + 1);
        }

        LOG.debug("reduceStart=" + reduceStart + ", mapDone=" + mapDone + ", reduceDone=" + reduceDone
                + ", reduceEndHeartbeat=" + reduceEndHeartbeat + ", killHeartbeat=" + killHeartbeat);

        final int numSlotsRequired = 1;
        org.apache.hadoop.mapred.TaskAttemptID taskIdOldApi = org.apache.hadoop.mapred.TaskAttemptID
                .downgrade(taskId);
        Task task = new ReduceTask("dummyjobfile", taskIdOldApi, 0, 0, numSlotsRequired);
        // all byte counters are 0
        TaskInfo taskInfo = new TaskInfo(0, 0, 0, 0, 0);
        ReduceTaskAttemptInfo taskAttemptInfo = new ReduceTaskAttemptInfo(State.SUCCEEDED, taskInfo, 0, 0,
                reduceRuntime);
        TaskTrackerAction action = new SimulatorLaunchTaskAction(task, taskAttemptInfo);
        heartbeats.get(reduceStart).get(taskTrackerName).addTaskTrackerAction(action);
        if (!isKilled || mapDone < killHeartbeat) {
            action = new AllMapsCompletedTaskAction(task.getTaskID());
            heartbeats.get(mapDone).get(taskTrackerName).addTaskTrackerAction(action);
        }
        if (isKilled) {
            action = new KillTaskAction(taskIdOldApi);
            heartbeats.get(killHeartbeat).get(taskTrackerName).addTaskTrackerAction(action);
        }

        for (long simulationTime = reduceStart
                + heartbeatInterval; simulationTime <= reduceEndHeartbeat; simulationTime += heartbeatInterval) {
            State state = simulationTime < reduceEndHeartbeat ? State.RUNNING : State.SUCCEEDED;
            if (simulationTime == reduceEndHeartbeat && isKilled) {
                state = State.KILLED;
            }
            // mapDone is when the all maps done event delivered
            Phase phase = simulationTime <= mapDone ? Phase.SHUFFLE : Phase.REDUCE;
            ReduceTaskStatus reduceStatus = new ReduceTaskStatus(task.getTaskID(), 0.0f, 0, state, "", "", null,
                    phase, null);
            heartbeats.get(simulationTime).get(taskTrackerName).addTaskReport(reduceStatus);
        }
    }

    // Should be called at the end of the simulation: Mock JT should have 
    // consumed all entries from the heartbeats table by that time
    public void checkMissingHeartbeats() {
        Assert.assertEquals(1, heartbeats.size());
        long lastHeartbeat = heartbeats.firstKey();
        Assert.assertTrue("Missing heartbeats, last heartbeat=" + lastHeartbeat,
                heartbeats.get(lastHeartbeat).isEmpty());
    }

    // rounds up to the next heartbeat time
    public long nextHeartbeat(long time) {
        long numHeartbeats = (long) Math.ceil((time - simulationStartTime) / (double) heartbeatInterval);
        return simulationStartTime + numHeartbeats * heartbeatInterval;
    }

    // Rest of InterTrackerProtocol follows, unused in simulation
    @Override
    public String getFilesystemName() {
        throw new UnsupportedOperationException();
    }

    @Override
    public void reportTaskTrackerError(String taskTracker, String errorClass, String errorMessage) {
        throw new UnsupportedOperationException();
    }

    @Override
    public TaskCompletionEvent[] getTaskCompletionEvents(JobID jobid, int fromEventId, int maxEvents) {
        throw new UnsupportedOperationException();
    }

    @Override
    public String getSystemDir() {
        throw new UnsupportedOperationException();
    }

    @Override
    public String getBuildVersion() {
        throw new UnsupportedOperationException();
    }

    @Override
    public long getProtocolVersion(String protocol, long clientVersion) {
        throw new UnsupportedOperationException();
    }

    @Override
    public TaskCompletionEvent[] getTaskCompletionEvents(org.apache.hadoop.mapred.JobID jobid, int fromEventId,
            int maxEvents) throws IOException {
        throw new UnsupportedOperationException();
    }

    @Override
    public TaskTrackerInfo[] getActiveTrackers() throws IOException, InterruptedException {
        throw new UnsupportedOperationException();
    }

    @Override
    public JobStatus[] getAllJobs() throws IOException, InterruptedException {
        throw new UnsupportedOperationException();
    }

    @Override
    public TaskTrackerInfo[] getBlacklistedTrackers() throws IOException, InterruptedException {
        throw new UnsupportedOperationException();
    }

    @Override
    public QueueInfo[] getChildQueues(String queueName) throws IOException, InterruptedException {
        throw new UnsupportedOperationException();
    }

    @Override
    public ClusterMetrics getClusterMetrics() throws IOException, InterruptedException {
        throw new UnsupportedOperationException();
    }

    @Override
    public Counters getJobCounters(JobID jobid) throws IOException, InterruptedException {
        throw new UnsupportedOperationException();
    }

    @Override
    public String getJobHistoryDir() throws IOException, InterruptedException {
        throw new UnsupportedOperationException();
    }

    @Override
    public JobStatus getJobStatus(JobID jobid) throws IOException, InterruptedException {
        throw new UnsupportedOperationException();
    }

    @Override
    public org.apache.hadoop.mapreduce.server.jobtracker.State getJobTrackerState()
            throws IOException, InterruptedException {
        throw new UnsupportedOperationException();
    }

    @Override
    public QueueInfo getQueue(String queueName) throws IOException, InterruptedException {
        throw new UnsupportedOperationException();

    }

    @Override
    public QueueAclsInfo[] getQueueAclsForCurrentUser() throws IOException, InterruptedException {
        throw new UnsupportedOperationException();

    }

    @Override
    public QueueInfo[] getQueues() throws IOException, InterruptedException {
        throw new UnsupportedOperationException();

    }

    @Override
    public QueueInfo[] getRootQueues() throws IOException, InterruptedException {
        throw new UnsupportedOperationException();

    }

    @Override
    public String[] getTaskDiagnostics(TaskAttemptID taskId) throws IOException, InterruptedException {
        throw new UnsupportedOperationException();
    }

    @Override
    public TaskReport[] getTaskReports(JobID jobid, TaskType type) throws IOException, InterruptedException {
        throw new UnsupportedOperationException();
    }

    @Override
    public long getTaskTrackerExpiryInterval() throws IOException, InterruptedException {
        throw new UnsupportedOperationException();
    }

    @Override
    public void killJob(JobID jobid) throws IOException, InterruptedException {
        throw new UnsupportedOperationException();
    }

    @Override
    public boolean killTask(TaskAttemptID taskId, boolean shouldFail) throws IOException, InterruptedException {
        throw new UnsupportedOperationException();
    }

    @Override
    public void setJobPriority(JobID jobid, String priority) throws IOException, InterruptedException {
        throw new UnsupportedOperationException();
    }

}