package org.apache.hadoop.hdfs;
import java.io.IOException;
import java.util.Random;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hdfs.server.namenode.AvatarNode;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.junit.After;
import org.junit.AfterClass;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
public class TestAvatarTxIds {
final static Log LOG = LogFactory.getLog(TestAvatarTxIds.class);
private MiniAvatarCluster cluster;
private Configuration conf;
private FileSystem fs;
private Random random = new Random();
@BeforeClass
public static void setUpBeforeClass() throws Exception {
MiniAvatarCluster.createAndStartZooKeeper();
}
@Before
public void setUp() throws Exception {
conf = new Configuration();
conf.setBoolean("fs.ha.retrywrites", true);
conf.setBoolean("fs.checkpoint.enabled", true);
cluster = new MiniAvatarCluster(conf, 3, true, null, null);
fs = cluster.getFileSystem();
}
@After
public void tearDown() throws Exception {
fs.close();
cluster.shutDown();
}
@AfterClass
public static void tearDownAfterClass() throws Exception {
MiniAvatarCluster.shutDownZooKeeper();
}
public void createEdits(int nEdits) throws IOException {
for (int i = 0; i < nEdits / 2; i++) {
// Create file ends up logging two edits to the edit log, one for create
// file and one for bumping up the generation stamp
fs.create(new Path("/" + random.nextInt()));
}
}
public long getCurrentTxId(AvatarNode avatar) {
return avatar.getFSImage().getEditLog().getCurrentTxId();
}
@Test
public void testBasic() throws Exception {
LOG.info("------------ testBasic-----------");
createEdits(20);
AvatarNode primary = cluster.getPrimaryAvatar(0).avatar;
AvatarNode standby = cluster.getStandbyAvatar(0).avatar;
standby.quiesceStandby(getCurrentTxId(primary)-1);
assertEquals(20, getCurrentTxId(primary));
assertEquals(getCurrentTxId(primary), getCurrentTxId(standby));
LOG.info("------------ testBasic----------- DONE");
}
@Test
public void testWithFailover() throws Exception {
LOG.info("------------ testWithFailover-----------");
// Create edits before failover.
createEdits(20);
AvatarNode primary = cluster.getPrimaryAvatar(0).avatar;
AvatarNode standby = cluster.getStandbyAvatar(0).avatar;
assertEquals(20, getCurrentTxId(primary));
// Perform failover and restart old primary.
cluster.failOver();
cluster.restartStandby();
// Get new instances after failover.
primary = cluster.getPrimaryAvatar(0).avatar;
standby = cluster.getStandbyAvatar(0).avatar;
assertEquals(20, getCurrentTxId(primary));
// Create some more edits and verify.
createEdits(20);
standby.quiesceStandby(getCurrentTxId(primary)-1);
assertEquals(40, getCurrentTxId(primary));
assertEquals(getCurrentTxId(primary), getCurrentTxId(standby));
LOG.info("------------ testWithFailover----------- DONE");
}
@Test
public void testWithFailoverTxIdMismatchHard() throws Exception {
LOG.info("------------ testWithFailoverTxIdMismatchHard-----------");
// Create edits before failover.
createEdits(20);
AvatarNode primary = cluster.getPrimaryAvatar(0).avatar;
AvatarNode standby = cluster.getStandbyAvatar(0).avatar;
assertEquals(20, getCurrentTxId(primary));
standby.getFSImage().getEditLog().setStartTransactionId(50);
assertEquals(50, getCurrentTxId(standby));
// close fs to avoid problem with its failover
// since the dfs failover is to fail in this test
fs.close();
// Perform failover and verify it fails.
try {
cluster.failOver();
} catch (IOException e) {
System.out.println("Expected exception : " + e);
LOG.info("------------ testWithFailoverTxIdMismatchHard----------- DONE");
return;
}
fail("Did not throw exception");
}
@Test
public void testDoubleFailover() throws Exception {
LOG.info("------------ testDoubleFailover-----------");
// Create edits before failover.
createEdits(20);
// Perform failover.
cluster.failOver();
cluster.restartStandby();
createEdits(20);
// Perform second failover.
cluster.failOver();
cluster.restartStandby();
createEdits(20);
AvatarNode primary = cluster.getPrimaryAvatar(0).avatar;
AvatarNode standby = cluster.getStandbyAvatar(0).avatar;
standby.quiesceStandby(getCurrentTxId(primary)-1);
assertEquals(60, getCurrentTxId(primary));
assertEquals(getCurrentTxId(primary), getCurrentTxId(standby));
LOG.info("------------ testDoubleFailover----------- DONE");
}
@Test
public void testWithStandbyDead() throws Exception {
LOG.info("------------ testWithStandbyDead-----------");
createEdits(20);
cluster.killStandby();
createEdits(20);
cluster.restartStandby();
createEdits(20);
AvatarNode primary = cluster.getPrimaryAvatar(0).avatar;
AvatarNode standby = cluster.getStandbyAvatar(0).avatar;
standby.quiesceStandby(getCurrentTxId(primary)-1);
assertEquals(60, getCurrentTxId(primary));
assertEquals(getCurrentTxId(primary), getCurrentTxId(standby));
LOG.info("------------ testWithStandbyDead----------- DONE");
}
@Test
public void testWithStandbyDeadAfterFailover() throws Exception {
LOG.info("------------ testWithStandbyDeadAfterFailover-----------");
createEdits(20);
cluster.failOver();
createEdits(20);
cluster.killStandby();
createEdits(20);
cluster.restartStandby();
createEdits(20);
AvatarNode primary = cluster.getPrimaryAvatar(0).avatar;
AvatarNode standby = cluster.getStandbyAvatar(0).avatar;
standby.quiesceStandby(getCurrentTxId(primary)-1);
assertEquals(80, getCurrentTxId(primary));
assertEquals(getCurrentTxId(primary), getCurrentTxId(standby));
LOG.info("------------ testWithStandbyDeadAfterFailover----------- DONE");
}
@Test
public void testWithCheckPoints() throws Exception {
LOG.info("------------ testWithCheckPoints-----------");
createEdits(20);
AvatarNode primary = cluster.getPrimaryAvatar(0).avatar;
AvatarNode standby = cluster.getStandbyAvatar(0).avatar;
standby.doCheckpoint();
createEdits(20);
standby.quiesceStandby(getCurrentTxId(primary)-1);
assertEquals(40, getCurrentTxId(primary));
assertEquals(getCurrentTxId(primary), getCurrentTxId(standby));
LOG.info("------------ testWithCheckPoints----------- DONE");
}
@Test
public void testAcrossRestarts() throws Exception {
LOG.info("------------ testAcrossRestarts-----------");
createEdits(20);
cluster.restartAvatarNodes();
AvatarNode primary = cluster.getPrimaryAvatar(0).avatar;
AvatarNode standby = cluster.getStandbyAvatar(0).avatar;
assertEquals(20, getCurrentTxId(primary));
assertEquals(getCurrentTxId(primary), getCurrentTxId(standby));
createEdits(20);
standby.quiesceStandby(getCurrentTxId(primary)-1);
assertEquals(40, getCurrentTxId(primary));
assertEquals(getCurrentTxId(primary), getCurrentTxId(standby));
LOG.info("------------ testAcrossRestarts----------- DONE");
}
@Test
public void testCheckpointAndRestart() throws Exception {
LOG.info("------------ testCheckpointAndRestart-----------");
createEdits(20);
AvatarNode primary = cluster.getPrimaryAvatar(0).avatar;
AvatarNode standby = cluster.getStandbyAvatar(0).avatar;
standby.doCheckpoint();
createEdits(20);
standby.quiesceStandby(getCurrentTxId(primary)-1);
assertEquals(40, getCurrentTxId(primary));
assertEquals(getCurrentTxId(primary), getCurrentTxId(standby));
cluster.restartAvatarNodes();
primary = cluster.getPrimaryAvatar(0).avatar;
standby = cluster.getStandbyAvatar(0).avatar;
createEdits(20);
standby.quiesceStandby(getCurrentTxId(primary)-1);
assertEquals(60, getCurrentTxId(primary));
assertEquals(getCurrentTxId(primary), getCurrentTxId(standby));
LOG.info("------------ testCheckpointAndRestart----------- DONE");
}
}