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

Java tutorial

Introduction

Here is the source code for org.apache.hadoop.mapred.JobTrackerHADaemon.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 com.google.common.annotations.VisibleForTesting;
import com.google.protobuf.BlockingService;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.concurrent.CountDownLatch;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.CommonConfigurationKeys;
import org.apache.hadoop.ha.HAServiceStatus;
import org.apache.hadoop.ha.proto.HAServiceProtocolProtos.HAServiceProtocolService;
import org.apache.hadoop.ha.protocolPB.HAServiceProtocolPB;
import org.apache.hadoop.ha.protocolPB.HAServiceProtocolServerSideTranslatorPB;
import org.apache.hadoop.ipc.ProtobufRpcEngine;
import org.apache.hadoop.ipc.RPC;
import org.apache.hadoop.ipc.WritableRpcEngine;
import org.apache.hadoop.mapreduce.Cluster;
import org.apache.hadoop.security.AccessControlException;
import org.apache.hadoop.security.SecurityUtil;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.util.ExitUtil;
import org.apache.hadoop.util.StringUtils;

import static org.apache.hadoop.util.ExitUtil.terminate;

public class JobTrackerHADaemon {

    static {
        Configuration.addDefaultResource("mapred-default.xml");
        Configuration.addDefaultResource("mapred-site.xml");
    }

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

    private Configuration conf;
    private JobTrackerRunner jtRunner;
    private JobTrackerHAServiceProtocol proto;
    private RPC.Server rpcServer;

    public JobTrackerHADaemon(Configuration conf) {
        this.conf = conf;
    }

    public Configuration getConf() {
        return conf;
    }

    public void start() throws IOException {

        Configuration jtConf = new Configuration(conf);
        String logicalName = HAUtil.getLogicalName(jtConf);
        String jtId = HAUtil.getJobTrackerId(jtConf);
        HAUtil.setGenericConf(jtConf, logicalName, jtId, HAUtil.JOB_TRACKER_SPECIFIC_KEYS);

        // Login HA daemon, if auth is not kerberos login() is a NOP
        InetSocketAddress addr = HAUtil.getJtHaRpcAddress(conf, jtId);
        String localMachine = addr.getHostName();
        UserGroupInformation.setConfiguration(conf);
        SecurityUtil.login(conf, JobTracker.JT_KEYTAB_FILE, JobTracker.JT_USER_NAME, localMachine);

        // To avoid the JT from doing a new login() as re-login seems to be destructive
        JobTracker.loggedIn = true;

        //Using a thread outside of all login context to start/stop the JT
        //otherwise the credentials of the UGI making the RPC call to activate
        //get in the way breaking things.
        jtRunner = new JobTrackerRunner();
        jtRunner.start();

        this.proto = new JobTrackerHAServiceProtocol(jtConf, jtRunner);

        RPC.setProtocolEngine(conf, HAServiceProtocolPB.class, ProtobufRpcEngine.class);

        HAServiceProtocolServerSideTranslatorPB haServiceProtocolXlator = new HAServiceProtocolServerSideTranslatorPB(
                proto);
        BlockingService haPbService = HAServiceProtocolService
                .newReflectiveBlockingService(haServiceProtocolXlator);

        WritableRpcEngine.ensureInitialized();

        InetSocketAddress rpcAddr = HAUtil.getJtHaRpcAddress(conf);

        this.rpcServer = RPC.getServer(HAServiceProtocolPB.class, haPbService, rpcAddr.getHostName(),
                rpcAddr.getPort(), conf);

        // set service-level authorization security policy
        if (conf.getBoolean(CommonConfigurationKeys.HADOOP_SECURITY_AUTHORIZATION, false)) {
            rpcServer.refreshServiceAcl(conf, new MapReducePolicyProvider());
        }

        this.rpcServer.start();

        // set port in config
        int port = rpcServer.getListenerAddress().getPort();
        HAUtil.setJtHaRpcAddress(conf, rpcAddr.getHostName() + ":" + port);
        LOG.info("Started " + getClass().getSimpleName() + " on port " + port);
    }

    public void makeActive() throws IOException {
        proto.transitionToActive(null);
    }

    public JobTracker getJobTracker() {
        return jtRunner.jt;
    }

    public JobTrackerHAServiceProtocol getJobTrackerHAServiceProtocol() {
        return proto;
    }

    public HAServiceStatus getServiceStatus() throws AccessControlException, IOException {
        return proto.getServiceStatus();
    }

    public void stop() throws IOException {
        proto.stop();
        rpcServer.stop();
    }

    /**
     * Wait for service to finish.
     * (Normally, it runs forever.)
     */
    public void join() {
        try {
            rpcServer.join();
        } catch (InterruptedException ie) {
            Thread.currentThread().interrupt();
        }
    }

    public static void startService() throws Exception {
        JobTrackerHADaemon daemon = new JobTrackerHADaemon(new Configuration());
        daemon.start();
        daemon.join();
    }

    public static void main(String[] args) {
        try {
            startService();
        } catch (Throwable e) {
            LOG.error(StringUtils.stringifyException(e));
            System.exit(-1);
        }
    }

    public static class JobTrackerRunner extends Thread {
        private JobTracker jt;
        private JobConf conf;
        private volatile CountDownLatch startLatch;
        private volatile CountDownLatch startedLatch;
        private volatile boolean jtClosing;
        private Thread jtThread;

        public JobTrackerRunner() {
            super(JobTrackerRunner.class.getSimpleName());
            setDaemon(true);
            startLatch = new CountDownLatch(1);
            startedLatch = new CountDownLatch(1);
        }

        public void run() {
            while (true) {
                try {
                    startLatch.await();
                    jt = JobTracker.startTracker(conf);
                    jtThread = new Thread(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                jt.offerService();
                            } catch (Throwable t) {
                                if (jtClosing) {
                                    LOG.info("Exception while closing jobtracker", t);
                                } else {
                                    doImmediateShutdown(t);
                                }
                            }
                        }
                    }, JobTrackerRunner.class.getSimpleName() + "-JT");
                    jtThread.start();
                    waitForRunningState();
                    startedLatch.countDown();
                    jtThread.join();
                } catch (Throwable t) {
                    doImmediateShutdown(t);
                } finally {
                    startedLatch.countDown();
                    startLatch = new CountDownLatch(1);
                    startedLatch = new CountDownLatch(1);
                }
            }
        }

        private void waitForRunningState() {
            while (jt != null
                    && jt.getClusterStatus(false).getJobTrackerStatus() != Cluster.JobTrackerStatus.RUNNING) {
                LOG.info("Waiting for jobtracker RUNNING state");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    Thread.interrupted();
                }
            }
        }

        /**
         * Shutdown the JT immediately in an ungraceful way. Used when it would be
         * unsafe for the JT to continue operating, e.g. during a failed HA state
         * transition.
         *
         * @param t exception which warrants the shutdown. Printed to the JT log
         *          before exit.
         * @throws org.apache.hadoop.util.ExitUtil.ExitException thrown only for testing.
         */
        private synchronized void doImmediateShutdown(Throwable t) throws ExitUtil.ExitException {
            String message = "Error encountered requiring JT shutdown. " + "Shutting down immediately.";
            try {
                LOG.fatal(message, t);
            } catch (Throwable ignored) {
                // This is unlikely to happen, but there's nothing we can do if it does.
            }
            terminate(1, t);
        }

        public void startJobTracker(JobConf conf) throws InterruptedException {
            if (jt == null) {
                this.conf = conf;
                startLatch.countDown();
                startedLatch.await();
            }
        }

        public void stopJobTracker() {
            try {
                if (jt != null) {
                    jtClosing = true;
                    jt.close();
                }
                if (jtThread != null) {
                    jtThread.join();
                }
            } catch (Throwable t) {
                doImmediateShutdown(t);
            }
            jt = null;
            jtClosing = false;
            jtThread = null;
        }

        public boolean jtThreadIsNotAlive() {
            return jtThread == null || !jtThread.isAlive();
        }

        @VisibleForTesting
        Thread getJobTrackerThread() {
            return jtThread;
        }

    }
}