org.apache.hadoop.hdfs.TestAvatarCleanShutdown.java Source code

Java tutorial

Introduction

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

import java.io.File;
import java.io.FileWriter;
import java.io.PrintWriter;

import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.FileUtil;
import org.apache.hadoop.fs.Path;

import org.junit.Test;
import org.junit.After;
import org.junit.BeforeClass;
import org.junit.AfterClass;

import static org.junit.Assert.*;

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

import org.apache.hadoop.conf.Configuration;
import java.util.Set;
import java.util.HashSet;

import org.apache.hadoop.hdfs.protocol.FSConstants;
import org.apache.hadoop.hdfs.server.datanode.AvatarDataNode;
import org.apache.hadoop.hdfs.util.InjectionEvent;
import org.apache.hadoop.hdfs.MiniAvatarCluster;
import org.apache.hadoop.hdfs.MiniAvatarCluster.DataNodeProperties;
import org.apache.hadoop.hdfs.MiniAvatarCluster.NameNodeInfo;
import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.util.InjectionEventI;
import org.apache.hadoop.util.InjectionHandler;

public class TestAvatarCleanShutdown {
    final static Log LOG = LogFactory.getLog(TestAvatarCleanShutdown.class);

    private static final String HOST_FILE_PATH = "/tmp/include_file";
    private String hosts;

    private Configuration conf;
    private MiniAvatarCluster cluster;
    private boolean federation;
    private Set<Thread> oldThreads;

    @BeforeClass
    public static void setUpStatic() throws Exception {
        MiniAvatarCluster.createAndStartZooKeeper();
    }

    public void setUp(String name) throws Exception {
        LOG.info("------------------- test: " + name + ", federation: " + federation + " START ----------------");
        oldThreads = new HashSet<Thread>(Thread.getAllStackTraces().keySet());

        conf = new Configuration();
        hosts = HOST_FILE_PATH + "_" + System.currentTimeMillis();
        File f = new File(hosts);
        f.delete();
        f.createNewFile();
        conf.set(FSConstants.DFS_HOSTS, hosts);
        conf.setInt("dfs.datanode.failed.volumes.tolerated", 0);
        if (!federation) {
            cluster = new MiniAvatarCluster.Builder(conf).build();
        } else {
            cluster = new MiniAvatarCluster.Builder(conf).numNameNodes(2).federation(true).build();
        }
        federation = false;
    }

    private void writeWrongIncludeFile(Configuration conf) throws Exception {
        String includeFN = conf.get(FSConstants.DFS_HOSTS, "");
        assertTrue(includeFN.equals(hosts));
        File f = new File(includeFN);
        if (f.exists()) {
            f.delete();
        }
        PrintWriter writer = new PrintWriter(new FileWriter(f, true));
        try {
            writer.println("FAKENAME");
        } finally {
            writer.close();
        }
    }

    @Test
    public void testVolumeFailureShutdown() throws Exception {
        setUp("testVolumeFailureShutdown");
        LOG.info("Corrupt the volume");
        DataNodeProperties dnp = cluster.getDataNodeProperties().get(0);
        String[] dataDirs = dnp.conf.getStrings("dfs.data.dir");
        File vol = new File(dataDirs[0], "current");
        try {
            assertEquals("Couldn't chmod local vol", 0, FileUtil.chmod(vol.toString(), "444"));
            cluster.restartDataNodes();
        } catch (Exception e) {
            LOG.warn("Expected exception", e);
        } finally {
            FileUtil.chmod(vol.toString(), "755");
            dnp.datanode.waitAndShutdown();
            cluster.shutDownAvatarNodes();
        }
    }

    @Test
    public void testRuntimeDisallowedDatanodeShutdown() throws Exception {
        setUp("testRuntimeDisallowedDatanodeShutdown");
        LOG.info("Update include file to not include datanode");
        NameNodeInfo nni = cluster.getNameNode(0);
        writeWrongIncludeFile(nni.conf);
        LOG.info("RefreshNodes with include file without datanode's hostname.");
        nni.avatars.get(0).avatar.namesystem.refreshNodes(nni.conf);
        nni.avatars.get(1).avatar.namesystem.refreshNodes(nni.conf);
        DataNodeProperties dnProp = cluster.getDataNodeProperties().get(0);
        AvatarDataNode dn = dnProp.datanode;
        dn.waitAndShutdown();
        cluster.shutDownAvatarNodes();
    }

    @Test
    public void testStartupDisallowedDatanodeShutdown() throws Exception {
        setUp("testStartupDisallowedDatanodeShutdown");
        LOG.info("Update include file to not include datanode");
        NameNodeInfo nni = cluster.getNameNode(0);
        writeWrongIncludeFile(nni.conf);
        LOG.info("Refresh hostReader internally with include file");
        nni.avatars.get(0).avatar.namesystem.getHostReader().refresh();
        nni.avatars.get(1).avatar.namesystem.getHostReader().refresh();
        LOG.info("Restart the datanode.");
        try {
            cluster.restartDataNodes();
        } catch (Exception e) {
            LOG.warn("Expected exception", e);
        }
        AvatarDataNode dn = cluster.getDataNodes().get(0);
        dn.waitAndShutdown();
        cluster.shutDownAvatarNodes();
    }

    @Test
    public void testNormalShutdown() throws Exception {
        setUp("testNormalShutdown");
        LOG.info("shutdown cluster");
        cluster.shutDown();
    }

    @Test
    public void testNormalShutdownFederation() throws Exception {
        federation = true;
        testNormalShutdown();
    }

    @Test
    public void testVolumeFailureShutdownFederation() throws Exception {
        federation = true;
        testVolumeFailureShutdown();
    }

    @Test
    public void testDataXeiverServerFailureShutdown() throws Exception {
        setUp("testDataXeiverServerFailureShutdown");
        LOG.info("Inject a RuntimeException to DataXeiverServer");
        InjectionHandler.set(new TestAvatarDatanodeShutdownHandler());
        final FileSystem fileSys = cluster.getFileSystem(0);
        FSDataOutputStream out = null;
        try {
            final Path fileName = new Path("/testFile");
            out = TestFileCreation.createFile(fileSys, fileName, cluster.getDataNodes().size());
            // trigger the failure
            TestFileCreation.writeFile(out);
        } finally {
            IOUtils.closeStream(out);
            fileSys.close();
            cluster.getDataNodes().get(0).waitAndShutdown();
            cluster.shutDownAvatarNodes();
        }
    }

    @Test
    public void testDataXeiverServerFailureShutdownFederation() throws Exception {
        federation = true;
        testDataXeiverServerFailureShutdown();
    }

    @After
    public void shutDown() throws Exception {
        if (cluster != null) {
            cluster.shutDown();
        }
        new File(hosts).delete();
        DFSTestThreadUtil.checkRemainingThreads(oldThreads);
    }

    @AfterClass
    public static void shutDownStatic() throws Exception {
        MiniAvatarCluster.shutDownZooKeeper();
    }

    private static class TestAvatarDatanodeShutdownHandler extends InjectionHandler {
        @Override
        protected void _processEvent(InjectionEventI event, Object... args) {
            LOG.debug("processEvent: processing event: " + event);

            if (event == InjectionEvent.AVATARXEIVER_RUNTIME_FAILURE) {
                throw new RuntimeException("Injected failure");
            }
        }
    }

}