| /* |
| * 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.server.datanode; |
| |
| import java.io.IOException; |
| |
| import org.apache.hadoop.fi.DataTransferTestUtil; |
| import org.apache.hadoop.fi.DataTransferTestUtil.DataNodeAction; |
| import org.apache.hadoop.fi.DataTransferTestUtil.DataTransferTest; |
| import org.apache.hadoop.fi.DataTransferTestUtil.DatanodeMarkingAction; |
| import org.apache.hadoop.fi.DataTransferTestUtil.IoeAction; |
| import org.apache.hadoop.fi.DataTransferTestUtil.OomAction; |
| import org.apache.hadoop.fi.DataTransferTestUtil.SleepAction; |
| import org.apache.hadoop.fi.FiTestUtil; |
| import org.apache.hadoop.fi.FiTestUtil.Action; |
| import org.apache.hadoop.fi.FiTestUtil.ConstraintSatisfactionAction; |
| import org.apache.hadoop.fi.FiTestUtil.MarkerConstraint; |
| import org.apache.hadoop.hdfs.protocol.DatanodeID; |
| import org.junit.Test; |
| |
| /** Test DataTransferProtocol with fault injection. */ |
| public class TestFiPipelineClose { |
| private static void runPipelineCloseTest(String methodName, |
| Action<DatanodeID, IOException> a) throws IOException { |
| FiTestUtil.LOG.info("Running " + methodName + " ..."); |
| final DataTransferTest t = (DataTransferTest) DataTransferTestUtil |
| .initTest(); |
| t.fiPipelineClose.set(a); |
| TestFiDataTransferProtocol.write1byte(methodName); |
| } |
| |
| /** |
| * Pipeline close: |
| * DN0 never responses after received close request from client. |
| * Client gets an IOException and determine DN0 bad. |
| */ |
| @Test |
| public void pipeline_Fi_36() throws IOException { |
| final String methodName = FiTestUtil.getMethodName(); |
| runPipelineCloseTest(methodName, new SleepAction(methodName, 0, 0)); |
| } |
| |
| /** |
| * Pipeline close: |
| * DN1 never responses after received close request from client. |
| * Client gets an IOException and determine DN1 bad. |
| */ |
| @Test |
| public void pipeline_Fi_37() throws IOException { |
| final String methodName = FiTestUtil.getMethodName(); |
| runPipelineCloseTest(methodName, new SleepAction(methodName, 1, 0)); |
| } |
| |
| /** |
| * Pipeline close: |
| * DN2 never responses after received close request from client. |
| * Client gets an IOException and determine DN2 bad. |
| */ |
| @Test |
| public void pipeline_Fi_38() throws IOException { |
| final String methodName = FiTestUtil.getMethodName(); |
| runPipelineCloseTest(methodName, new SleepAction(methodName, 2, 0)); |
| } |
| |
| private static void run41_43(String name, int i) throws IOException { |
| runPipelineCloseTest(name, new SleepAction(name, i, 3000)); |
| } |
| |
| private static void runPipelineCloseAck(String name, int i, DataNodeAction a |
| ) throws IOException { |
| FiTestUtil.LOG.info("Running " + name + " ..."); |
| final DataTransferTest t = (DataTransferTest)DataTransferTestUtil.initTest(); |
| final MarkerConstraint marker = new MarkerConstraint(name); |
| t.fiPipelineClose.set(new DatanodeMarkingAction(name, i, marker)); |
| t.fiPipelineAck.set(new ConstraintSatisfactionAction<DatanodeID, IOException>(a, marker)); |
| TestFiDataTransferProtocol.write1byte(name); |
| } |
| |
| private static void run39_40(String name, int i) throws IOException { |
| runPipelineCloseAck(name, i, new SleepAction(name, i, 0)); |
| } |
| |
| /** |
| * Pipeline close: |
| * DN1 never responses after received close ack DN2. |
| * Client gets an IOException and determine DN1 bad. |
| */ |
| @Test |
| public void pipeline_Fi_39() throws IOException { |
| run39_40(FiTestUtil.getMethodName(), 1); |
| } |
| |
| /** |
| * Pipeline close: |
| * DN0 never responses after received close ack DN1. |
| * Client gets an IOException and determine DN0 bad. |
| */ |
| @Test |
| public void pipeline_Fi_40() throws IOException { |
| run39_40(FiTestUtil.getMethodName(), 0); |
| } |
| |
| /** |
| * Pipeline close with DN0 very slow but it won't lead to timeout. |
| * Client finishes close successfully. |
| */ |
| @Test |
| public void pipeline_Fi_41() throws IOException { |
| run41_43(FiTestUtil.getMethodName(), 0); |
| } |
| |
| /** |
| * Pipeline close with DN1 very slow but it won't lead to timeout. |
| * Client finishes close successfully. |
| */ |
| @Test |
| public void pipeline_Fi_42() throws IOException { |
| run41_43(FiTestUtil.getMethodName(), 1); |
| } |
| |
| /** |
| * Pipeline close with DN2 very slow but it won't lead to timeout. |
| * Client finishes close successfully. |
| */ |
| @Test |
| public void pipeline_Fi_43() throws IOException { |
| run41_43(FiTestUtil.getMethodName(), 2); |
| } |
| |
| /** |
| * Pipeline close: |
| * DN0 throws an OutOfMemoryException |
| * right after it received a close request from client. |
| * Client gets an IOException and determine DN0 bad. |
| */ |
| @Test |
| public void pipeline_Fi_44() throws IOException { |
| final String methodName = FiTestUtil.getMethodName(); |
| runPipelineCloseTest(methodName, new OomAction(methodName, 0)); |
| } |
| |
| /** |
| * Pipeline close: |
| * DN1 throws an OutOfMemoryException |
| * right after it received a close request from client. |
| * Client gets an IOException and determine DN1 bad. |
| */ |
| @Test |
| public void pipeline_Fi_45() throws IOException { |
| final String methodName = FiTestUtil.getMethodName(); |
| runPipelineCloseTest(methodName, new OomAction(methodName, 1)); |
| } |
| |
| /** |
| * Pipeline close: |
| * DN2 throws an OutOfMemoryException |
| * right after it received a close request from client. |
| * Client gets an IOException and determine DN2 bad. |
| */ |
| @Test |
| public void pipeline_Fi_46() throws IOException { |
| final String methodName = FiTestUtil.getMethodName(); |
| runPipelineCloseTest(methodName, new OomAction(methodName, 2)); |
| } |
| |
| private static void run47_48(String name, int i) throws IOException { |
| runPipelineCloseAck(name, i, new OomAction(name, i)); |
| } |
| |
| /** |
| * Pipeline close: |
| * DN1 throws an OutOfMemoryException right after |
| * it received a close ack from DN2. |
| * Client gets an IOException and determine DN1 bad. |
| */ |
| @Test |
| public void pipeline_Fi_47() throws IOException { |
| run47_48(FiTestUtil.getMethodName(), 1); |
| } |
| |
| /** |
| * Pipeline close: |
| * DN0 throws an OutOfMemoryException right after |
| * it received a close ack from DN1. |
| * Client gets an IOException and determine DN0 bad. |
| */ |
| @Test |
| public void pipeline_Fi_48() throws IOException { |
| run47_48(FiTestUtil.getMethodName(), 0); |
| } |
| |
| private static void runBlockFileCloseTest(String methodName, |
| Action<DatanodeID, IOException> a) throws IOException { |
| FiTestUtil.LOG.info("Running " + methodName + " ..."); |
| final DataTransferTest t = (DataTransferTest) DataTransferTestUtil |
| .initTest(); |
| t.fiBlockFileClose.set(a); |
| TestFiDataTransferProtocol.write1byte(methodName); |
| } |
| |
| private static void run49_51(String name, int i) throws IOException { |
| runBlockFileCloseTest(name, new IoeAction(name, i, "DISK ERROR")); |
| } |
| |
| /** |
| * Pipeline close: |
| * DN0 throws a disk error exception when it is closing the block file. |
| * Client gets an IOException and determine DN0 bad. |
| */ |
| @Test |
| public void pipeline_Fi_49() throws IOException { |
| run49_51(FiTestUtil.getMethodName(), 0); |
| } |
| |
| |
| /** |
| * Pipeline close: |
| * DN1 throws a disk error exception when it is closing the block file. |
| * Client gets an IOException and determine DN1 bad. |
| */ |
| @Test |
| public void pipeline_Fi_50() throws IOException { |
| run49_51(FiTestUtil.getMethodName(), 1); |
| } |
| |
| /** |
| * Pipeline close: |
| * DN2 throws a disk error exception when it is closing the block file. |
| * Client gets an IOException and determine DN2 bad. |
| */ |
| @Test |
| public void pipeline_Fi_51() throws IOException { |
| run49_51(FiTestUtil.getMethodName(), 2); |
| } |
| } |