Skip to content

Commit 254abc4

Browse files
committed
Provided implementation for FaultInjectorFileIoEvents
1 parent 8b56456 commit 254abc4

File tree

6 files changed

+554
-29
lines changed

6 files changed

+554
-29
lines changed

hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/DFSConfigKeys.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1202,6 +1202,10 @@ public class DFSConfigKeys extends CommonConfigurationKeys {
12021202
"dfs.datanode.enable.fileio.fault.injection";
12031203
public static final boolean
12041204
DFS_DATANODE_ENABLE_FILEIO_FAULT_INJECTION_DEFAULT = false;
1205+
public static final String DFS_DATANODE_ENABLED_OPS_FILEIO_FAULT_INJECTION_KEY =
1206+
"dfs.datanode.fileio.fault.injection.operations";
1207+
public static final String DFS_DATANODE_FILEIO_FAULT_PERCENTAGE_KEY =
1208+
"dfs.datanode.fileio.fault.percentage";
12051209
public static final String
12061210
DFS_DATANODE_FILEIO_PROFILING_SAMPLING_PERCENTAGE_KEY =
12071211
"dfs.datanode.fileio.profiling.sampling.percentage";

hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/FaultInjectorFileIoEvents.java

Lines changed: 87 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,23 @@
1818

1919
package org.apache.hadoop.hdfs.server.datanode;
2020

21+
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_DATANODE_ENABLED_OPS_FILEIO_FAULT_INJECTION_KEY;
22+
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_DATANODE_ENABLE_FILEIO_FAULT_INJECTION_DEFAULT;
23+
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_DATANODE_ENABLE_FILEIO_FAULT_INJECTION_KEY;
24+
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_DATANODE_FILEIO_FAULT_PERCENTAGE_KEY;
25+
26+
import java.util.HashSet;
27+
import java.util.Set;
28+
import java.util.concurrent.ThreadLocalRandom;
29+
30+
import javax.annotation.Nullable;
2131

2232
import org.apache.hadoop.classification.InterfaceAudience;
33+
import org.apache.hadoop.classification.VisibleForTesting;
2334
import org.apache.hadoop.conf.Configuration;
24-
import org.apache.hadoop.hdfs.DFSConfigKeys;
2535
import org.apache.hadoop.hdfs.server.datanode.fsdataset.FsVolumeSpi;
26-
27-
import javax.annotation.Nullable;
36+
import org.slf4j.Logger;
37+
import org.slf4j.LoggerFactory;
2838

2939
/**
3040
* Injects faults in the metadata and data related operations on datanode
@@ -33,23 +43,90 @@
3343
@InterfaceAudience.Private
3444
public class FaultInjectorFileIoEvents {
3545

46+
public static final class InjectedFileIOFaultException extends Exception {
47+
48+
private static final long serialVersionUID = 1L;
49+
50+
private InjectedFileIOFaultException() {
51+
super("Fault injected by configuration");
52+
}
53+
}
54+
55+
public static final Logger LOG = LoggerFactory.getLogger(
56+
FaultInjectorFileIoEvents.class);
57+
3658
private final boolean isEnabled;
59+
private final Set<FileIoProvider.OPERATION> configuredOps;
60+
private final int faultRangeMax;
3761

3862
public FaultInjectorFileIoEvents(@Nullable Configuration conf) {
3963
if (conf != null) {
40-
isEnabled = conf.getBoolean(DFSConfigKeys
41-
.DFS_DATANODE_ENABLE_FILEIO_FAULT_INJECTION_KEY, DFSConfigKeys
42-
.DFS_DATANODE_ENABLE_FILEIO_FAULT_INJECTION_DEFAULT);
64+
isEnabled = conf.getBoolean(
65+
DFS_DATANODE_ENABLE_FILEIO_FAULT_INJECTION_KEY,
66+
DFS_DATANODE_ENABLE_FILEIO_FAULT_INJECTION_DEFAULT);
4367
} else {
4468
isEnabled = false;
4569
}
70+
configuredOps = new HashSet<>();
71+
if (isEnabled) {
72+
String ops = conf.get(
73+
DFS_DATANODE_ENABLED_OPS_FILEIO_FAULT_INJECTION_KEY);
74+
if (ops != null) {
75+
String[] parts = ops.split(",");
76+
for (String part : parts) {
77+
String opName = part.trim().toUpperCase();
78+
try {
79+
configuredOps.add(FileIoProvider.OPERATION.valueOf(opName));
80+
} catch (IllegalArgumentException e) {
81+
LOG.warn("Value '{}' is not valid FileIoProvider.OPERATION, "
82+
+ "ignoring...", opName);
83+
}
84+
}
85+
}
86+
int faultPercentagePropVal = Math.min(conf.getInt(
87+
DFS_DATANODE_FILEIO_FAULT_PERCENTAGE_KEY, 0), 100);
88+
faultRangeMax = (int) ((double) faultPercentagePropVal / 100 *
89+
Integer.MAX_VALUE);
90+
LOG.warn("FaultInjectorFileIoEvents is enabled and will fail the "
91+
+ "following operations: {}", configuredOps);
92+
LOG.warn(" *** DO NOT USE IN PRODUCTION!!! ***");
93+
} else {
94+
faultRangeMax = 0;
95+
}
96+
}
97+
98+
@VisibleForTesting
99+
boolean isEnabled() {
100+
return isEnabled;
101+
}
102+
103+
@VisibleForTesting
104+
Set<FileIoProvider.OPERATION> getOperations() {
105+
return configuredOps;
106+
}
107+
108+
@VisibleForTesting
109+
int getFaultRangeMax() {
110+
return faultRangeMax;
111+
}
112+
113+
private void fault(FileIoProvider.OPERATION op)
114+
throws InjectedFileIOFaultException {
115+
if (isEnabled && faultRangeMax > 0 && configuredOps.contains(op)
116+
&& ThreadLocalRandom.current().nextInt() < faultRangeMax) {
117+
LOG.error("Throwing fault for operation: " + op);
118+
throw new InjectedFileIOFaultException();
119+
}
46120
}
47121

48-
public void beforeMetadataOp(
49-
@Nullable FsVolumeSpi volume, FileIoProvider.OPERATION op) {
122+
public void beforeMetadataOp(@Nullable FsVolumeSpi volume,
123+
FileIoProvider.OPERATION op) throws InjectedFileIOFaultException {
124+
fault(op);
50125
}
51126

52-
public void beforeFileIo(
53-
@Nullable FsVolumeSpi volume, FileIoProvider.OPERATION op, long len) {
127+
public void beforeFileIo(@Nullable FsVolumeSpi volume,
128+
FileIoProvider.OPERATION op, long len)
129+
throws InjectedFileIOFaultException {
130+
fault(op);
54131
}
55132
}

0 commit comments

Comments
 (0)