/** * 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 org.apache.hadoop.hdfs.server.namenode.AvatarNode; import org.apache.hadoop.hdfs.server.namenode.ZookeeperTxId; import org.apache.hadoop.util.InjectionHandler; import org.apache.hadoop.fs.Path; import org.apache.zookeeper.KeeperException.NoNodeException; import static org.junit.Assert.*; import org.junit.Test; public class TestAvatarSyncLastTxid extends FailoverTestUtil { @Test public void testBasic() throws Exception { setUp("testBasic"); createEdits(20); // fs.close() creates 10 more edits due to close file ops. fs.close(); cluster.shutDown(); // +3 initial checkpoint +1 shutdown verifyState(34); } @Test public void testPrimaryCrash() throws Exception { setUp("testPrimaryCrash"); createEdits(20); fs.close(); InjectionHandler.set(new FailoverTestUtilHandler()); cluster.getPrimaryAvatar(0).avatar.shutdownAvatar(); InjectionHandler.clear(); ZookeeperTxId lastTxId = null; try { lastTxId = getLastTxid(); } catch (NoNodeException e) { LOG.info("Expected exception", e); assertNull(lastTxId); return; } fail("Did not throw : " + NoNodeException.class); } @Test public void testPrimaryCrashWithExistingZkNode() throws Exception { setUp("testPrimaryCrashWithExistingZkNode"); // First do a clean shutdown. createEdits(20); // fs.close() creates 10 more edits due to close file ops. fs.close(); cluster.shutDown(); // 3 for initial checkpoint + 1 shutdown verifyState(34); // Now we have an existing znode with the last transaction id, now do an // unclean shutdown and verify session ids don't match. cluster = new MiniAvatarCluster(conf, 3, true, null, null); fs = cluster.getFileSystem(); createEdits(20); fs.close(); InjectionHandler.set(new FailoverTestUtilHandler()); cluster.getPrimaryAvatar(0).avatar.shutdownAvatar(); InjectionHandler.clear(); ZookeeperTxId lastTxId = null; try { lastTxId = getLastTxid(); } catch (NoNodeException e) { LOG.info("Expected exception", e); assertNull(lastTxId); return; } fail("Did not throw : " + NoNodeException.class); } @Test public void testWithFailover() throws Exception { setUp("testWithFailover"); createEdits(20); cluster.failOver(); createEdits(20); // 20 edits since we are closing 20 files. fs.close(); } @Test public void testWithDoubleFailover() throws Exception { setUp("testWithDoubleFailover"); // Perform first failover createEdits(20); cluster.failOver(); createEdits(20); cluster.restartStandby(); // Perform second failover. createEdits(20); cluster.failOver(); createEdits(20); // 40 edits since we are closing 40 files. fs.close(); } @Test public void testFailoverWithPrimaryCrash() throws Exception { setUp("testFailoverWithPrimaryCrash"); createEdits(20); fs.close(); InjectionHandler.set(new FailoverTestUtilHandler()); cluster.killPrimary(0, true); InjectionHandler.clear(); try { cluster.failOver(); } catch (Exception e) { LOG.info("Expected exception", e); return; } fail("Did not throw exception"); } @Test public void testDoubleFailoverWithPrimaryCrash() throws Exception { setUp("testDoubleFailoverWithPrimaryCrash"); // First failover createEdits(20); cluster.failOver(); cluster.restartStandby(); createEdits(20); fs.close(); // Second failover. InjectionHandler.set(new FailoverTestUtilHandler()); cluster.killPrimary(0, true); InjectionHandler.clear(); try { cluster.failOver(); } catch (Exception e) { LOG.info("Expected exception : ", e); return; } fail("Did not throw : " + NoNodeException.class); } @Test public void testFailoverAfterUnsuccessfulFailover() throws Exception { setUp("testFailoverAfterUnsuccessfulFailover"); createEdits(20); fs.close(); InjectionHandler.set(new FailoverTestUtilHandler()); cluster.killPrimary(0, true); InjectionHandler.clear(); try { cluster.failOver(); } catch (Exception e) { LOG.info("Expected exception : ", e); // Now restart avatarnodes and do a clean failover. cluster.restartAvatarNodes(); fs = cluster.getFileSystem(); createEdits(20); cluster.failOver(); return; } fail("Did not throw exception"); } @Test public void testEditLogCrash() throws Exception { setUp("testEditLogCrash", false); FailoverTestUtilHandler h = new FailoverTestUtilHandler(); h.simulateEditLogCrash = true; InjectionHandler.set(h); cluster.shutDown(); conf.setBoolean("fs.ha.retrywrites", true); cluster = new MiniAvatarCluster.Builder(conf).numDataNodes(3).enableQJM(false).build(); fs = cluster.getFileSystem(); zkClient = new AvatarZooKeeperClient(conf, null); createEdits(20); // These 20 edits should not be persisted, since edit log is going to crash. createEditsNotSynced(20); try { cluster.failOver(); } catch (Exception e) { LOG.info("Expected exception : ", e); // initial checkpoint 3 + 20 assertEquals(23, cluster.getStandbyAvatar(0).avatar.getLastWrittenTxId() + 1); return; } fail("Did not throw exception"); } @Test public void testBlocksMisMatch() throws Exception { setUp("testBlocksMisMatch", false); int totalBlocks = 50; DFSTestUtil.createFile(fs, new Path("/testBlocksMisMatch"), (long) totalBlocks * 1024, (short) 3, System.currentTimeMillis()); AvatarNode standby = cluster.getStandbyAvatar(0).avatar; standby.quiesceStandby(cluster .getPrimaryAvatar(0).avatar.getLastWrittenTxId()); // This sets the standby number of blocks to 0. standby.namesystem.close(); try { cluster.failOver(); } catch (Exception e) { LOG.info("Expected exception : ", e); return; } fail("Did not throw exception"); } }