|
@@ -22,6 +22,8 @@ import static org.junit.Assert.assertTrue;
|
|
|
import static org.junit.Assert.fail;
|
|
|
|
|
|
import java.io.IOException;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
+import java.util.concurrent.TimeoutException;
|
|
|
import java.util.concurrent.atomic.AtomicInteger;
|
|
|
|
|
|
import org.apache.hadoop.conf.Configuration;
|
|
@@ -34,6 +36,7 @@ import org.apache.hadoop.hdfs.MiniDFSCluster;
|
|
|
import org.apache.hadoop.hdfs.protocol.HdfsConstants;
|
|
|
import org.apache.hadoop.hdfs.qjournal.MiniQJMHACluster;
|
|
|
import org.apache.hadoop.hdfs.server.namenode.NameNode;
|
|
|
+import org.apache.hadoop.hdfs.server.namenode.NameNodeAdapter;
|
|
|
import org.apache.hadoop.ipc.RpcScheduler;
|
|
|
import org.apache.hadoop.ipc.Schedulable;
|
|
|
import org.apache.hadoop.test.GenericTestUtils;
|
|
@@ -57,7 +60,7 @@ public class TestConsistentReadsObserver {
|
|
|
private static Configuration conf;
|
|
|
private static MiniQJMHACluster qjmhaCluster;
|
|
|
private static MiniDFSCluster dfsCluster;
|
|
|
- private static DistributedFileSystem dfs;
|
|
|
+ private DistributedFileSystem dfs;
|
|
|
|
|
|
private final Path testPath= new Path("/TestConsistentReadsObserver");
|
|
|
|
|
@@ -74,7 +77,7 @@ public class TestConsistentReadsObserver {
|
|
|
|
|
|
@Before
|
|
|
public void setUp() throws Exception {
|
|
|
- setObserverRead(true);
|
|
|
+ dfs = setObserverRead(true);
|
|
|
}
|
|
|
|
|
|
@After
|
|
@@ -106,8 +109,7 @@ public class TestConsistentReadsObserver {
|
|
|
configuration.setBoolean(prefix
|
|
|
+ CommonConfigurationKeys.IPC_BACKOFF_ENABLE, true);
|
|
|
|
|
|
- dfsCluster.restartNameNode(observerIdx);
|
|
|
- dfsCluster.transitionToObserver(observerIdx);
|
|
|
+ NameNodeAdapter.getRpcServer(nn).refreshCallQueue(configuration);
|
|
|
|
|
|
dfs.create(testPath, (short)1).close();
|
|
|
assertSentTo(0);
|
|
@@ -151,18 +153,26 @@ public class TestConsistentReadsObserver {
|
|
|
assertEquals(1, readStatus.get());
|
|
|
}
|
|
|
|
|
|
- @Test
|
|
|
- public void testMsync() throws Exception {
|
|
|
+ private void testMsync(boolean autoMsync, long autoMsyncPeriodMs)
|
|
|
+ throws Exception {
|
|
|
// 0 == not completed, 1 == succeeded, -1 == failed
|
|
|
AtomicInteger readStatus = new AtomicInteger(0);
|
|
|
Configuration conf2 = new Configuration(conf);
|
|
|
|
|
|
// Disable FS cache so two different DFS clients will be used.
|
|
|
conf2.setBoolean("fs.hdfs.impl.disable.cache", true);
|
|
|
+ if (autoMsync) {
|
|
|
+ conf2.setTimeDuration(
|
|
|
+ ObserverReadProxyProvider.AUTO_MSYNC_PERIOD_KEY_PREFIX
|
|
|
+ + "." + dfs.getUri().getHost(),
|
|
|
+ autoMsyncPeriodMs, TimeUnit.MILLISECONDS);
|
|
|
+ }
|
|
|
DistributedFileSystem dfs2 = (DistributedFileSystem) FileSystem.get(conf2);
|
|
|
|
|
|
// Initialize the proxies for Observer Node.
|
|
|
dfs.getClient().getHAServiceState();
|
|
|
+ // This initialization will perform the msync-on-startup, so that another
|
|
|
+ // form of msync is required later
|
|
|
dfs2.getClient().getHAServiceState();
|
|
|
|
|
|
// Advance Observer's state ID so it is ahead of client's.
|
|
@@ -176,7 +186,12 @@ public class TestConsistentReadsObserver {
|
|
|
try {
|
|
|
// After msync, client should have the latest state ID from active.
|
|
|
// Therefore, the subsequent getFileStatus call should succeed.
|
|
|
- dfs2.getClient().msync();
|
|
|
+ if (!autoMsync) {
|
|
|
+ // If not testing auto-msync, perform an explicit one here
|
|
|
+ dfs2.getClient().msync();
|
|
|
+ } else if (autoMsyncPeriodMs > 0) {
|
|
|
+ Thread.sleep(autoMsyncPeriodMs);
|
|
|
+ }
|
|
|
dfs2.getFileStatus(testPath);
|
|
|
if (HATestUtil.isSentToAnyOfNameNodes(dfs2, dfsCluster, 2)) {
|
|
|
readStatus.set(1);
|
|
@@ -196,10 +211,31 @@ public class TestConsistentReadsObserver {
|
|
|
|
|
|
dfsCluster.rollEditLogAndTail(0);
|
|
|
|
|
|
- GenericTestUtils.waitFor(() -> readStatus.get() != 0, 100, 10000);
|
|
|
+ GenericTestUtils.waitFor(() -> readStatus.get() != 0, 100, 3000);
|
|
|
assertEquals(1, readStatus.get());
|
|
|
}
|
|
|
|
|
|
+ @Test
|
|
|
+ public void testExplicitMsync() throws Exception {
|
|
|
+ testMsync(false, -1);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testAutoMsyncPeriod0() throws Exception {
|
|
|
+ testMsync(true, 0);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testAutoMsyncPeriod5() throws Exception {
|
|
|
+ testMsync(true, 5);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test(expected = TimeoutException.class)
|
|
|
+ public void testAutoMsyncLongPeriod() throws Exception {
|
|
|
+ // This should fail since the auto-msync is never activated
|
|
|
+ testMsync(true, Long.MAX_VALUE);
|
|
|
+ }
|
|
|
+
|
|
|
// A new client should first contact the active, before using an observer,
|
|
|
// to ensure that it is up-to-date with the current state
|
|
|
@Test
|
|
@@ -313,8 +349,8 @@ public class TestConsistentReadsObserver {
|
|
|
HATestUtil.isSentToAnyOfNameNodes(dfs, dfsCluster, nnIdx));
|
|
|
}
|
|
|
|
|
|
- private static void setObserverRead(boolean flag) throws Exception {
|
|
|
- dfs = HATestUtil.configureObserverReadFs(
|
|
|
+ private DistributedFileSystem setObserverRead(boolean flag) throws Exception {
|
|
|
+ return HATestUtil.configureObserverReadFs(
|
|
|
dfsCluster, conf, ObserverReadProxyProvider.class, flag);
|
|
|
}
|
|
|
|