Skip to content

Commit 08da854

Browse files
author
freedom
committed
HDFS-16083: Forbid Observer NameNode trigger active namenode roll edits log
1 parent e91daae commit 08da854

File tree

6 files changed

+158
-8
lines changed

6 files changed

+158
-8
lines changed

hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1576,7 +1576,8 @@ void startStandbyServices(final Configuration conf, boolean isObserver)
15761576

15771577
// Disable quota checks while in standby.
15781578
dir.disableQuotaChecks();
1579-
editLogTailer = new EditLogTailer(this, conf);
1579+
boolean shouldTriggerActiveLogRoll = isObserver ? false : true;
1580+
editLogTailer = new EditLogTailer(this, conf , shouldTriggerActiveLogRoll);
15801581
editLogTailer.start();
15811582
if (!isObserver && standbyShouldCheckpoint) {
15821583
standbyCheckpointer = new StandbyCheckpointer(conf, this);

hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/ha/EditLogTailer.java

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -178,8 +178,9 @@ public class EditLogTailer {
178178
*/
179179
private Timer timer;
180180

181-
public EditLogTailer(FSNamesystem namesystem, Configuration conf) {
182-
this.tailerThread = new EditLogTailerThread();
181+
public EditLogTailer(FSNamesystem namesystem, Configuration conf,
182+
boolean shouldTriggerActiveLogRoll) {
183+
this.tailerThread = new EditLogTailerThread(shouldTriggerActiveLogRoll);
183184
this.conf = conf;
184185
this.namesystem = namesystem;
185186
this.timer = new Timer();
@@ -476,14 +477,21 @@ void sleep(long sleepTimeMillis) throws InterruptedException {
476477
*/
477478
private class EditLogTailerThread extends Thread {
478479
private volatile boolean shouldRun = true;
480+
private final boolean shouldTriggerActiveLogRoll;
479481

480-
private EditLogTailerThread() {
482+
private EditLogTailerThread(boolean shouldTriggerActiveLogRoll) {
481483
super("Edit log tailer");
484+
this.shouldTriggerActiveLogRoll = shouldTriggerActiveLogRoll;
482485
}
483486

484487
private void setShouldRun(boolean shouldRun) {
485488
this.shouldRun = shouldRun;
486489
}
490+
491+
@VisibleForTesting
492+
public long getLastRollTimeMs(){
493+
return lastRollTimeMs;
494+
}
487495

488496
@Override
489497
public void run() {
@@ -507,7 +515,8 @@ private void doWork() {
507515
// triggered.
508516
boolean triggeredLogRoll = false;
509517
if (tooLongSinceLastLoad() &&
510-
lastRollTriggerTxId < lastLoadedTxnId) {
518+
lastRollTriggerTxId < lastLoadedTxnId &&
519+
shouldTriggerActiveLogRoll) {
511520
triggerActiveLogRoll();
512521
triggeredLogRoll = true;
513522
}

hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/ha/TestDelegationTokensWithHA.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ public void testDelegationTokenDFSApi() throws Exception {
203203

204204
private class EditLogTailerForTest extends EditLogTailer {
205205
public EditLogTailerForTest(FSNamesystem namesystem, Configuration conf) {
206-
super(namesystem, conf);
206+
super(namesystem, conf, true);
207207
}
208208

209209
public void catchupDuringFailover() throws IOException {

hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/ha/TestEditLogTailer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ public void testTailerBackoff() throws Exception {
177177
final Queue<Long> sleepDurations = new ConcurrentLinkedQueue<>();
178178
final int zeroEditCount = 5;
179179
final AtomicInteger tailEditsCallCount = new AtomicInteger(0);
180-
EditLogTailer tailer = new EditLogTailer(mockNamesystem, conf) {
180+
EditLogTailer tailer = new EditLogTailer(mockNamesystem, conf, true) {
181181
@Override
182182
void sleep(long sleepTimeMs) {
183183
if (sleepDurations.size() <= zeroEditCount) {

hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/ha/TestObserverNode.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ public void testObserverRequeue() throws Exception {
164164
FileStatus fileStatus = scheduledFuture.get(10000, TimeUnit.MILLISECONDS);
165165
assertNotNull(fileStatus);
166166
} finally {
167-
EditLogTailer editLogTailer = new EditLogTailer(observerFsNS, conf);
167+
EditLogTailer editLogTailer = new EditLogTailer(observerFsNS, conf, false);
168168
observerFsNS.setEditLogTailerForTests(editLogTailer);
169169
editLogTailer.start();
170170
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
package org.apache.hadoop.hdfs.server.namenode.ha;
19+
20+
import org.apache.hadoop.conf.Configuration;
21+
import org.apache.hadoop.hdfs.DFSConfigKeys;
22+
import org.apache.hadoop.hdfs.MiniDFSCluster;
23+
import org.apache.hadoop.hdfs.qjournal.MiniQJMHACluster;
24+
import org.apache.hadoop.hdfs.server.namenode.NameNode;
25+
import org.junit.AfterClass;
26+
import org.junit.Assert;
27+
import org.junit.BeforeClass;
28+
import org.junit.Test;
29+
30+
import java.io.IOException;
31+
import java.util.concurrent.TimeUnit;
32+
33+
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_STATE_CONTEXT_ENABLED_KEY;
34+
import static org.apache.hadoop.hdfs.server.namenode.ha.ObserverReadProxyProvider.OBSERVER_PROBE_RETRY_PERIOD_KEY;
35+
import static org.junit.Assert.assertEquals;
36+
import static org.junit.Assert.assertTrue;
37+
38+
public class TestStandbyRollEditsLogOnly {
39+
private static Configuration conf;
40+
private static MiniQJMHACluster qjmhaCluster;
41+
private static MiniDFSCluster dfsCluster;
42+
@BeforeClass
43+
public static void startUpCluster() throws Exception {
44+
conf = new Configuration();
45+
conf.setBoolean(DFS_NAMENODE_STATE_CONTEXT_ENABLED_KEY, true);
46+
conf.set(DFSConfigKeys.DFS_HA_LOGROLL_PERIOD_KEY, "5");
47+
conf.setTimeDuration(
48+
OBSERVER_PROBE_RETRY_PERIOD_KEY, 0, TimeUnit.MILLISECONDS);
49+
qjmhaCluster = HATestUtil.setUpObserverCluster(conf, 1, 1, true);
50+
dfsCluster = qjmhaCluster.getDfsCluster();
51+
}
52+
53+
@Test
54+
public void testOnlyStandbyRollEditlog() throws IOException,
55+
InterruptedException {
56+
dfsCluster.transitionToActive(0);
57+
dfsCluster.transitionToStandby(1);
58+
dfsCluster.transitionToObserver(2);
59+
dfsCluster.waitActive();
60+
NameNode standbyNameNode = dfsCluster.getNameNode(1);
61+
NameNode observerNameNode = dfsCluster.getNameNode(2);
62+
Assert.assertEquals("transitionToStandby failed !",
63+
"standby",standbyNameNode.getNamesystem().getHAState() );
64+
Assert.assertEquals("transitionToObserver failed !",
65+
"observer",observerNameNode.getNamesystem().getHAState());
66+
67+
long standbyInitialRollTime =
68+
standbyNameNode.getNamesystem().getEditLogTailer().getLastRollTimeMs();
69+
long observerInitialRollTime =
70+
observerNameNode.getNamesystem().getEditLogTailer().getLastRollTimeMs();
71+
//wait for roll edits log
72+
Thread.sleep(6000);
73+
long standbyLastRollTime =
74+
standbyNameNode.getNamesystem().getEditLogTailer().getLastRollTimeMs();
75+
long observerLastRollTime =
76+
observerNameNode.getNamesystem().getEditLogTailer().getLastRollTimeMs();
77+
assertTrue("Standby should roll the log!",
78+
standbyLastRollTime > standbyInitialRollTime);
79+
assertEquals("The observer is not expected to roll the log.",
80+
observerInitialRollTime , observerLastRollTime);
81+
}
82+
83+
@Test
84+
public void testTransObToStandbyThenRollLog() throws IOException,
85+
InterruptedException {
86+
87+
int standbyNameNodeIndex = getStandbyNameNode();
88+
int observerNameNodeIndex = getObserverNameNode();
89+
assert standbyNameNodeIndex > 0;
90+
assert observerNameNodeIndex > 0;
91+
dfsCluster.transitionToObserver(standbyNameNodeIndex);
92+
dfsCluster.transitionToStandby(observerNameNodeIndex);
93+
NameNode standbyNameNode = dfsCluster.getNameNode(observerNameNodeIndex);
94+
NameNode observerNameNode = dfsCluster.getNameNode(standbyNameNodeIndex);
95+
Assert.assertEquals("transitionToStandby failed !",
96+
"standby",standbyNameNode.getNamesystem().getHAState() );
97+
Assert.assertEquals("transitionToObserver failed !",
98+
"observer",observerNameNode.getNamesystem().getHAState());
99+
100+
long standbyInitialRollTime =
101+
standbyNameNode.getNamesystem().getEditLogTailer().getLastRollTimeMs();
102+
long observerInitialRollTime =
103+
observerNameNode.getNamesystem().getEditLogTailer().getLastRollTimeMs();
104+
//wait for roll edits log
105+
Thread.sleep(6000);
106+
long standbyLastRollTime =
107+
standbyNameNode.getNamesystem().getEditLogTailer().getLastRollTimeMs();
108+
long observerLastRollTime =
109+
observerNameNode.getNamesystem().getEditLogTailer().getLastRollTimeMs();
110+
assertTrue("Standby should roll the log",
111+
standbyLastRollTime > standbyInitialRollTime);
112+
Assert.assertEquals("The observer is not expected to roll the log.",
113+
observerInitialRollTime , observerLastRollTime);
114+
}
115+
116+
private int getObserverNameNode(){
117+
for (int i = 0; i < dfsCluster.getNumNameNodes(); i++) {
118+
if(dfsCluster.getNameNode(i).isObserverState()){
119+
return i;
120+
}
121+
}
122+
return -1;
123+
}
124+
125+
private int getStandbyNameNode(){
126+
for (int i = 0; i < dfsCluster.getNumNameNodes(); i++) {
127+
if(dfsCluster.getNameNode(i).isStandbyState()){
128+
return i;
129+
}
130+
}
131+
return -1;
132+
}
133+
134+
@AfterClass
135+
public static void shutDownCluster() throws IOException {
136+
if (qjmhaCluster != null) {
137+
qjmhaCluster.shutdown();
138+
}
139+
}
140+
}

0 commit comments

Comments
 (0)