HDFS-16007. Deserialization of ReplicaState should avoid throwing ArrayIndexOutOfBoundsException (#2982)
Signed-off-by: Akira Ajisaka <aajisaka@apache.org>
(cherry picked from commit b944084b32
)
This commit is contained in:
parent
f5ef78d46f
commit
3176ab028b
@ -23,6 +23,7 @@
|
|||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.Validate;
|
||||||
import org.apache.hadoop.classification.InterfaceAudience;
|
import org.apache.hadoop.classification.InterfaceAudience;
|
||||||
import org.apache.hadoop.fs.Path;
|
import org.apache.hadoop.fs.Path;
|
||||||
import org.apache.hadoop.hdfs.DFSUtil;
|
import org.apache.hadoop.hdfs.DFSUtil;
|
||||||
@ -294,6 +295,10 @@ enum ReplicaState {
|
|||||||
/** Temporary replica: created for replication and relocation only. */
|
/** Temporary replica: created for replication and relocation only. */
|
||||||
TEMPORARY(4);
|
TEMPORARY(4);
|
||||||
|
|
||||||
|
// Since ReplicaState (de)serialization depends on ordinal, either adding
|
||||||
|
// new value should be avoided to this enum or newly appended value should
|
||||||
|
// be handled by NameNodeLayoutVersion#Feature.
|
||||||
|
|
||||||
private static final ReplicaState[] cachedValues = ReplicaState.values();
|
private static final ReplicaState[] cachedValues = ReplicaState.values();
|
||||||
|
|
||||||
private final int value;
|
private final int value;
|
||||||
@ -306,13 +311,32 @@ public int getValue() {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve ReplicaState corresponding to given index.
|
||||||
|
*
|
||||||
|
* @param v Index to retrieve {@link ReplicaState}.
|
||||||
|
* @return {@link ReplicaState} object.
|
||||||
|
* @throws IndexOutOfBoundsException if the index is invalid.
|
||||||
|
*/
|
||||||
public static ReplicaState getState(int v) {
|
public static ReplicaState getState(int v) {
|
||||||
|
Validate.validIndex(cachedValues, v, "Index Expected range: [0, "
|
||||||
|
+ (cachedValues.length - 1) + "]. Actual value: " + v);
|
||||||
return cachedValues[v];
|
return cachedValues[v];
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Read from in */
|
/**
|
||||||
|
* Retrieve ReplicaState corresponding to index provided in binary stream.
|
||||||
|
*
|
||||||
|
* @param in Index value provided as bytes in given binary stream.
|
||||||
|
* @return {@link ReplicaState} object.
|
||||||
|
* @throws IOException if an I/O error occurs while reading bytes.
|
||||||
|
* @throws IndexOutOfBoundsException if the index is invalid.
|
||||||
|
*/
|
||||||
public static ReplicaState read(DataInput in) throws IOException {
|
public static ReplicaState read(DataInput in) throws IOException {
|
||||||
return cachedValues[in.readByte()];
|
byte idx = in.readByte();
|
||||||
|
Validate.validIndex(cachedValues, idx, "Index Expected range: [0, "
|
||||||
|
+ (cachedValues.length - 1) + "]. Actual value: " + idx);
|
||||||
|
return cachedValues[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Write to out */
|
/** Write to out */
|
||||||
|
@ -457,6 +457,25 @@ public void testReadWriteReplicaState() {
|
|||||||
out.reset();
|
out.reset();
|
||||||
in.reset();
|
in.reset();
|
||||||
}
|
}
|
||||||
|
out = new DataOutputBuffer();
|
||||||
|
out.writeByte(100);
|
||||||
|
in.reset(out.getData(), out.getLength());
|
||||||
|
try {
|
||||||
|
HdfsServerConstants.ReplicaState.read(in);
|
||||||
|
fail("Should not have reached here");
|
||||||
|
} catch (IndexOutOfBoundsException e) {
|
||||||
|
assertEquals(e.getMessage(),
|
||||||
|
"Index Expected range: [0, 4]. Actual value: 100");
|
||||||
|
}
|
||||||
|
out.reset();
|
||||||
|
in.reset();
|
||||||
|
try {
|
||||||
|
HdfsServerConstants.ReplicaState.getState(200);
|
||||||
|
fail("Should not have reached here");
|
||||||
|
} catch (IndexOutOfBoundsException e) {
|
||||||
|
assertEquals(e.getMessage(),
|
||||||
|
"Index Expected range: [0, 4]. Actual value: 200");
|
||||||
|
}
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
fail("testReadWrite ex error ReplicaState");
|
fail("testReadWrite ex error ReplicaState");
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user