Skip to content

Commit e56a8fc

Browse files
committed
HBASE-28721 AsyncFSWAL is broken when running against hadoop 3.4.0 (#6270)
Signed-off-by: Duo Zhang <zhangduo@apache.org> (cherry picked from commit c18921a)
1 parent 22f80ff commit e56a8fc

File tree

2 files changed

+87
-25
lines changed

2 files changed

+87
-25
lines changed

hbase-asyncfs/src/main/java/org/apache/hadoop/hbase/io/asyncfs/FanOutOneBlockAsyncDFSOutput.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
import org.apache.hadoop.hdfs.protocol.ClientProtocol;
6161
import org.apache.hadoop.hdfs.protocol.DatanodeInfo;
6262
import org.apache.hadoop.hdfs.protocol.ExtendedBlock;
63+
import org.apache.hadoop.hdfs.protocol.HdfsFileStatus;
6364
import org.apache.hadoop.hdfs.protocol.LocatedBlock;
6465
import org.apache.hadoop.hdfs.protocol.datatransfer.PacketHeader;
6566
import org.apache.hadoop.hdfs.protocol.datatransfer.PipelineAck;
@@ -121,7 +122,7 @@ public class FanOutOneBlockAsyncDFSOutput implements AsyncFSOutput {
121122

122123
private final String src;
123124

124-
private final long fileId;
125+
private HdfsFileStatus stat;
125126

126127
private final ExtendedBlock block;
127128

@@ -354,14 +355,14 @@ private void setupReceiver(int timeoutMs) {
354355
}
355356

356357
FanOutOneBlockAsyncDFSOutput(Configuration conf, DistributedFileSystem dfs, DFSClient client,
357-
ClientProtocol namenode, String clientName, String src, long fileId, LocatedBlock locatedBlock,
358-
Encryptor encryptor, Map<Channel, DatanodeInfo> datanodeInfoMap, DataChecksum summer,
359-
ByteBufAllocator alloc, StreamSlowMonitor streamSlowMonitor) {
358+
ClientProtocol namenode, String clientName, String src, HdfsFileStatus stat,
359+
LocatedBlock locatedBlock, Encryptor encryptor, Map<Channel, DatanodeInfo> datanodeInfoMap,
360+
DataChecksum summer, ByteBufAllocator alloc, StreamSlowMonitor streamSlowMonitor) {
360361
this.conf = conf;
361362
this.dfs = dfs;
362363
this.client = client;
363364
this.namenode = namenode;
364-
this.fileId = fileId;
365+
this.stat = stat;
365366
this.clientName = clientName;
366367
this.src = src;
367368
this.block = locatedBlock.getBlock();
@@ -592,7 +593,7 @@ public void recoverAndClose(CancelableProgressable reporter) throws IOException
592593
buf = null;
593594
}
594595
closeDataNodeChannelsAndAwait();
595-
endFileLease(client, fileId);
596+
endFileLease(client, stat);
596597
RecoverLeaseFSUtils.recoverFileLease(dfs, new Path(src), conf,
597598
reporter == null ? new CancelOnClose(client) : reporter);
598599
}
@@ -607,7 +608,7 @@ public void close() throws IOException {
607608
state = State.CLOSED;
608609
closeDataNodeChannelsAndAwait();
609610
block.setNumBytes(ackedBlockLength);
610-
completeFile(client, namenode, src, clientName, block, fileId);
611+
completeFile(client, namenode, src, clientName, block, stat);
611612
}
612613

613614
@Override

hbase-asyncfs/src/main/java/org/apache/hadoop/hbase/io/asyncfs/FanOutOneBlockAsyncDFSOutputHelper.java

Lines changed: 79 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -141,9 +141,9 @@ private FanOutOneBlockAsyncDFSOutputHelper() {
141141

142142
private interface LeaseManager {
143143

144-
void begin(DFSClient client, long inodeId);
144+
void begin(DFSClient client, HdfsFileStatus stat);
145145

146-
void end(DFSClient client, long inodeId);
146+
void end(DFSClient client, HdfsFileStatus stat);
147147
}
148148

149149
private static final LeaseManager LEASE_MANAGER;
@@ -202,7 +202,58 @@ public boolean isClientRunning(DFSClient client) {
202202
};
203203
}
204204

205-
private static LeaseManager createLeaseManager() throws NoSuchMethodException {
205+
private static LeaseManager createLeaseManager3_4() throws NoSuchMethodException {
206+
Method beginFileLeaseMethod =
207+
DFSClient.class.getDeclaredMethod("beginFileLease", String.class, DFSOutputStream.class);
208+
beginFileLeaseMethod.setAccessible(true);
209+
Method endFileLeaseMethod = DFSClient.class.getDeclaredMethod("endFileLease", String.class);
210+
endFileLeaseMethod.setAccessible(true);
211+
Method getConfigurationMethod = DFSClient.class.getDeclaredMethod("getConfiguration");
212+
getConfigurationMethod.setAccessible(true);
213+
Method getNamespaceMehtod = HdfsFileStatus.class.getDeclaredMethod("getNamespace");
214+
215+
return new LeaseManager() {
216+
217+
private static final String DFS_OUTPUT_STREAM_UNIQ_DEFAULT_KEY =
218+
"dfs.client.output.stream.uniq.default.key";
219+
private static final String DFS_OUTPUT_STREAM_UNIQ_DEFAULT_KEY_DEFAULT = "DEFAULT";
220+
221+
private String getUniqId(DFSClient client, HdfsFileStatus stat)
222+
throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
223+
// Copied from DFSClient in Hadoop 3.4.0
224+
long fileId = stat.getFileId();
225+
String namespace = (String) getNamespaceMehtod.invoke(stat);
226+
if (namespace == null) {
227+
Configuration conf = (Configuration) getConfigurationMethod.invoke(client);
228+
String defaultKey = conf.get(DFS_OUTPUT_STREAM_UNIQ_DEFAULT_KEY,
229+
DFS_OUTPUT_STREAM_UNIQ_DEFAULT_KEY_DEFAULT);
230+
return defaultKey + "_" + fileId;
231+
} else {
232+
return namespace + "_" + fileId;
233+
}
234+
}
235+
236+
@Override
237+
public void begin(DFSClient client, HdfsFileStatus stat) {
238+
try {
239+
beginFileLeaseMethod.invoke(client, getUniqId(client, stat), null);
240+
} catch (IllegalAccessException | InvocationTargetException e) {
241+
throw new RuntimeException(e);
242+
}
243+
}
244+
245+
@Override
246+
public void end(DFSClient client, HdfsFileStatus stat) {
247+
try {
248+
endFileLeaseMethod.invoke(client, getUniqId(client, stat));
249+
} catch (IllegalAccessException | InvocationTargetException e) {
250+
throw new RuntimeException(e);
251+
}
252+
}
253+
};
254+
}
255+
256+
private static LeaseManager createLeaseManager3() throws NoSuchMethodException {
206257
Method beginFileLeaseMethod =
207258
DFSClient.class.getDeclaredMethod("beginFileLease", long.class, DFSOutputStream.class);
208259
beginFileLeaseMethod.setAccessible(true);
@@ -211,25 +262,35 @@ private static LeaseManager createLeaseManager() throws NoSuchMethodException {
211262
return new LeaseManager() {
212263

213264
@Override
214-
public void begin(DFSClient client, long inodeId) {
265+
public void begin(DFSClient client, HdfsFileStatus stat) {
215266
try {
216-
beginFileLeaseMethod.invoke(client, inodeId, null);
267+
beginFileLeaseMethod.invoke(client, stat.getFileId(), null);
217268
} catch (IllegalAccessException | InvocationTargetException e) {
218269
throw new RuntimeException(e);
219270
}
220271
}
221272

222273
@Override
223-
public void end(DFSClient client, long inodeId) {
274+
public void end(DFSClient client, HdfsFileStatus stat) {
224275
try {
225-
endFileLeaseMethod.invoke(client, inodeId);
276+
endFileLeaseMethod.invoke(client, stat.getFileId());
226277
} catch (IllegalAccessException | InvocationTargetException e) {
227278
throw new RuntimeException(e);
228279
}
229280
}
230281
};
231282
}
232283

284+
private static LeaseManager createLeaseManager() throws NoSuchMethodException {
285+
try {
286+
return createLeaseManager3_4();
287+
} catch (NoSuchMethodException e) {
288+
LOG.debug("DFSClient::beginFileLease wrong arguments, should be hadoop 3.3 or below");
289+
}
290+
291+
return createLeaseManager3();
292+
}
293+
233294
private static FileCreator createFileCreator3_3() throws NoSuchMethodException {
234295
Method createMethod = ClientProtocol.class.getMethod("create", String.class, FsPermission.class,
235296
String.class, EnumSetWritable.class, boolean.class, short.class, long.class,
@@ -320,12 +381,12 @@ public boolean progress() {
320381
}
321382
}
322383

323-
static void beginFileLease(DFSClient client, long inodeId) {
324-
LEASE_MANAGER.begin(client, inodeId);
384+
static void beginFileLease(DFSClient client, HdfsFileStatus stat) {
385+
LEASE_MANAGER.begin(client, stat);
325386
}
326387

327-
static void endFileLease(DFSClient client, long inodeId) {
328-
LEASE_MANAGER.end(client, inodeId);
388+
static void endFileLease(DFSClient client, HdfsFileStatus stat) {
389+
LEASE_MANAGER.end(client, stat);
329390
}
330391

331392
static DataChecksum createChecksum(DFSClient client) {
@@ -552,7 +613,7 @@ private static FanOutOneBlockAsyncDFSOutput createOutput(DistributedFileSystem d
552613
throw new NameNodeException(e);
553614
}
554615
}
555-
beginFileLease(client, stat.getFileId());
616+
beginFileLease(client, stat);
556617
boolean succ = false;
557618
LocatedBlock locatedBlock = null;
558619
List<Future<Channel>> futureList = null;
@@ -576,8 +637,8 @@ private static FanOutOneBlockAsyncDFSOutput createOutput(DistributedFileSystem d
576637
}
577638
Encryptor encryptor = createEncryptor(conf, stat, client);
578639
FanOutOneBlockAsyncDFSOutput output =
579-
new FanOutOneBlockAsyncDFSOutput(conf, dfs, client, namenode, clientName, src,
580-
stat.getFileId(), locatedBlock, encryptor, datanodes, summer, ALLOC, monitor);
640+
new FanOutOneBlockAsyncDFSOutput(conf, dfs, client, namenode, clientName, src, stat,
641+
locatedBlock, encryptor, datanodes, summer, ALLOC, monitor);
581642
succ = true;
582643
return output;
583644
} catch (RemoteException e) {
@@ -616,7 +677,7 @@ public void operationComplete(Future<Channel> future) throws Exception {
616677
});
617678
}
618679
}
619-
endFileLease(client, stat.getFileId());
680+
endFileLease(client, stat);
620681
}
621682
}
622683
}
@@ -654,11 +715,11 @@ public static boolean shouldRetryCreate(RemoteException e) {
654715
}
655716

656717
static void completeFile(DFSClient client, ClientProtocol namenode, String src, String clientName,
657-
ExtendedBlock block, long fileId) {
718+
ExtendedBlock block, HdfsFileStatus stat) {
658719
for (int retry = 0;; retry++) {
659720
try {
660-
if (namenode.complete(src, clientName, block, fileId)) {
661-
endFileLease(client, fileId);
721+
if (namenode.complete(src, clientName, block, stat.getFileId())) {
722+
endFileLease(client, stat);
662723
return;
663724
} else {
664725
LOG.warn("complete file " + src + " not finished, retry = " + retry);

0 commit comments

Comments
 (0)