HDFS-4962. Merging change r1501851 from trunk

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/branches/branch-2@1509386 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Brandon Li 2013-08-01 19:05:28 +00:00
parent d7f082ad5f
commit d3946f980a
21 changed files with 263 additions and 227 deletions

View File

@ -26,14 +26,31 @@ import org.apache.hadoop.oncrpc.XDR;
* requests. See RFC 1094 for more details. * requests. See RFC 1094 for more details.
*/ */
public interface MountInterface { public interface MountInterface {
public static int MNTPROC_NULL = 0; /** Mount procedures */
public static int MNTPROC_MNT = 1; public static enum MNTPROC {
public static int MNTPROC_DUMP = 2; // the order of the values below are significant.
public static int MNTPROC_UMNT = 3; NULL,
public static int MNTPROC_UMNTALL = 4; MNT,
public static int MNTPROC_EXPORT = 5; DUMP,
public static int MNTPROC_EXPORTALL = 6; UMNT,
public static int MNTPROC_PATHCONF = 7; UMNTALL,
EXPORT,
EXPORTALL,
PATHCONF;
/** @return the int value representing the procedure. */
public int getValue() {
return ordinal();
}
/** @return the procedure corresponding to the value. */
public static MNTPROC fromValue(int value) {
if (value < 0 || value >= values().length) {
return null;
}
return values()[value];
}
}
/** MNTPROC_NULL - Do Nothing */ /** MNTPROC_NULL - Do Nothing */
public XDR nullOp(XDR out, int xid, InetAddress client); public XDR nullOp(XDR out, int xid, InetAddress client);

View File

@ -33,7 +33,7 @@ public class MountResponse {
private MountResponse() { private MountResponse() {
} }
/** Response for RPC call {@link MountInterface#MNTPROC_MNT} */ /** Response for RPC call {@link MountInterface.MNTPROC#MNT} */
public static XDR writeMNTResponse(int status, XDR xdr, int xid, public static XDR writeMNTResponse(int status, XDR xdr, int xid,
byte[] handle) { byte[] handle) {
RpcAcceptedReply.voidReply(xdr, xid); RpcAcceptedReply.voidReply(xdr, xid);
@ -48,7 +48,7 @@ public class MountResponse {
return xdr; return xdr;
} }
/** Response for RPC call {@link MountInterface#MNTPROC_DUMP} */ /** Response for RPC call {@link MountInterface.MNTPROC#DUMP} */
public static XDR writeMountList(XDR xdr, int xid, List<MountEntry> mounts) { public static XDR writeMountList(XDR xdr, int xid, List<MountEntry> mounts) {
RpcAcceptedReply.voidReply(xdr, xid); RpcAcceptedReply.voidReply(xdr, xid);
for (MountEntry mountEntry : mounts) { for (MountEntry mountEntry : mounts) {
@ -60,7 +60,7 @@ public class MountResponse {
return xdr; return xdr;
} }
/** Response for RPC call {@link MountInterface#MNTPROC_EXPORT} */ /** Response for RPC call {@link MountInterface.MNTPROC#EXPORT} */
public static XDR writeExportList(XDR xdr, int xid, List<String> exports) { public static XDR writeExportList(XDR xdr, int xid, List<String> exports) {
RpcAcceptedReply.voidReply(xdr, xid); RpcAcceptedReply.voidReply(xdr, xid);
for (String export : exports) { for (String export : exports) {

View File

@ -17,6 +17,7 @@
*/ */
package org.apache.hadoop.nfs.nfs3; package org.apache.hadoop.nfs.nfs3;
/** /**
* Some constants for NFSv3 * Some constants for NFSv3
*/ */
@ -34,28 +35,58 @@ public class Nfs3Constant {
public final static int VERSION = 3; public final static int VERSION = 3;
// The procedures // The procedures
public final static int NFSPROC3_NULL = 0; public static enum NFSPROC3 {
public final static int NFSPROC3_GETATTR = 1; // the order of the values below are significant.
public final static int NFSPROC3_SETATTR = 2; NULL,
public final static int NFSPROC3_LOOKUP = 3; GETATTR,
public final static int NFSPROC3_ACCESS = 4; SETATTR,
public final static int NFSPROC3_READLINK = 5; LOOKUP,
public final static int NFSPROC3_READ = 6; ACCESS,
public final static int NFSPROC3_WRITE = 7; READLINK,
public final static int NFSPROC3_CREATE = 8; READ,
public final static int NFSPROC3_MKDIR = 9; WRITE,
public final static int NFSPROC3_SYMLINK = 10; CREATE(false),
public final static int NFSPROC3_MKNOD = 11; MKDIR(false),
public final static int NFSPROC3_REMOVE = 12; SYMLINK(false),
public final static int NFSPROC3_RMDIR = 13; MKNOD(false),
public final static int NFSPROC3_RENAME = 14; REMOVE(false),
public final static int NFSPROC3_LINK = 15; RMDIR(false),
public final static int NFSPROC3_READDIR = 16; RENAME(false),
public final static int NFSPROC3_READDIRPLUS = 17; LINK(false),
public final static int NFSPROC3_FSSTAT = 18; READDIR,
public final static int NFSPROC3_FSINFO = 19; READDIRPLUS,
public final static int NFSPROC3_PATHCONF = 20; FSSTAT,
public final static int NFSPROC3_COMMIT = 21; FSINFO,
PATHCONF,
COMMIT;
private final boolean isIdempotent;
private NFSPROC3(boolean isIdempotent) {
this.isIdempotent = isIdempotent;
}
private NFSPROC3() {
this(true);
}
public boolean isIdempotent() {
return isIdempotent;
}
/** @return the int value representing the procedure. */
public int getValue() {
return ordinal();
}
/** @return the procedure corresponding to the value. */
public static NFSPROC3 fromValue(int value) {
if (value < 0 || value >= values().length) {
return null;
}
return values()[value];
}
}
// The maximum size in bytes of the opaque file handle. // The maximum size in bytes of the opaque file handle.
public final static int NFS3_FHSIZE = 64; public final static int NFS3_FHSIZE = 64;
@ -125,16 +156,13 @@ public class Nfs3Constant {
/** Write call flavors */ /** Write call flavors */
public enum WriteStableHow { public enum WriteStableHow {
UNSTABLE(0), DATA_SYNC(1), FILE_SYNC(2); // the order of the values below are significant.
UNSTABLE,
private final int id; DATA_SYNC,
FILE_SYNC;
WriteStableHow(int id) {
this.id = id;
}
public int getValue() { public int getValue() {
return id; return ordinal();
} }
public static WriteStableHow fromValue(int id) { public static WriteStableHow fromValue(int id) {

View File

@ -25,39 +25,34 @@ import org.apache.hadoop.oncrpc.RpcAuthInfo.AuthFlavor;
*/ */
public class RpcAcceptedReply extends RpcReply { public class RpcAcceptedReply extends RpcReply {
public enum AcceptState { public enum AcceptState {
SUCCESS(0), /* RPC executed successfully */ // the order of the values below are significant.
PROG_UNAVAIL(1), /* remote hasn't exported program */ SUCCESS, /* RPC executed successfully */
PROG_MISMATCH(2), /* remote can't support version # */ PROG_UNAVAIL, /* remote hasn't exported program */
PROC_UNAVAIL(3), /* program can't support procedure */ PROG_MISMATCH, /* remote can't support version # */
GARBAGE_ARGS(4), /* procedure can't decode params */ PROC_UNAVAIL, /* program can't support procedure */
SYSTEM_ERR(5); /* e.g. memory allocation failure */ GARBAGE_ARGS, /* procedure can't decode params */
SYSTEM_ERR; /* e.g. memory allocation failure */
private final int value;
AcceptState(int value) {
this.value = value;
}
public static AcceptState fromValue(int value) { public static AcceptState fromValue(int value) {
return values()[value]; return values()[value];
} }
public int getValue() { public int getValue() {
return value; return ordinal();
} }
}; };
private final RpcAuthInfo verifier; private final RpcAuthInfo verifier;
private final AcceptState acceptState; private final AcceptState acceptState;
RpcAcceptedReply(int xid, int messageType, ReplyState state, RpcAcceptedReply(int xid, RpcMessage.Type messageType, ReplyState state,
RpcAuthInfo verifier, AcceptState acceptState) { RpcAuthInfo verifier, AcceptState acceptState) {
super(xid, messageType, state); super(xid, messageType, state);
this.verifier = verifier; this.verifier = verifier;
this.acceptState = acceptState; this.acceptState = acceptState;
} }
public static RpcAcceptedReply read(int xid, int messageType, public static RpcAcceptedReply read(int xid, RpcMessage.Type messageType,
ReplyState replyState, XDR xdr) { ReplyState replyState, XDR xdr) {
RpcAuthInfo verifier = RpcAuthInfo.read(xdr); RpcAuthInfo verifier = RpcAuthInfo.read(xdr);
AcceptState acceptState = AcceptState.fromValue(xdr.readInt()); AcceptState acceptState = AcceptState.fromValue(xdr.readInt());
@ -79,7 +74,7 @@ public class RpcAcceptedReply extends RpcReply {
public static XDR voidReply(XDR xdr, int xid, AcceptState acceptState) { public static XDR voidReply(XDR xdr, int xid, AcceptState acceptState) {
xdr.writeInt(xid); xdr.writeInt(xid);
xdr.writeInt(RpcMessage.RPC_REPLY); xdr.writeInt(RpcMessage.Type.RPC_REPLY.getValue());
xdr.writeInt(ReplyState.MSG_ACCEPTED.getValue()); xdr.writeInt(ReplyState.MSG_ACCEPTED.getValue());
xdr.writeInt(AuthFlavor.AUTH_NONE.getValue()); xdr.writeInt(AuthFlavor.AUTH_NONE.getValue());
xdr.writeVariableOpaque(new byte[0]); xdr.writeVariableOpaque(new byte[0]);

View File

@ -33,7 +33,7 @@ public class RpcCall extends RpcMessage {
private final RpcAuthInfo credential; private final RpcAuthInfo credential;
private final RpcAuthInfo verifier; private final RpcAuthInfo verifier;
protected RpcCall(int xid, int messageType, int rpcVersion, int program, protected RpcCall(int xid, RpcMessage.Type messageType, int rpcVersion, int program,
int version, int procedure, RpcAuthInfo credential, RpcAuthInfo verifier) { int version, int procedure, RpcAuthInfo credential, RpcAuthInfo verifier) {
super(xid, messageType); super(xid, messageType);
this.rpcVersion = rpcVersion; this.rpcVersion = rpcVersion;
@ -56,7 +56,7 @@ public class RpcCall extends RpcMessage {
} }
public void validate() { public void validate() {
validateMessageType(RPC_CALL); validateMessageType(RpcMessage.Type.RPC_CALL);
validateRpcVersion(); validateRpcVersion();
// Validate other members // Validate other members
// Throw exception if validation fails // Throw exception if validation fails
@ -88,7 +88,8 @@ public class RpcCall extends RpcMessage {
} }
public static RpcCall read(XDR xdr) { public static RpcCall read(XDR xdr) {
return new RpcCall(xdr.readInt(), xdr.readInt(), xdr.readInt(), xdr.readInt(), return new RpcCall(xdr.readInt(), RpcMessage.Type.fromValue(xdr.readInt()),
xdr.readInt(), xdr.readInt(),
xdr.readInt(), xdr.readInt(), RpcAuthInfo.read(xdr), xdr.readInt(), xdr.readInt(), RpcAuthInfo.read(xdr),
RpcAuthInfo.read(xdr)); RpcAuthInfo.read(xdr));
} }
@ -96,7 +97,7 @@ public class RpcCall extends RpcMessage {
public static void write(XDR out, int xid, int program, int progVersion, public static void write(XDR out, int xid, int program, int progVersion,
int procedure) { int procedure) {
out.writeInt(xid); out.writeInt(xid);
out.writeInt(RpcMessage.RPC_CALL); out.writeInt(RpcMessage.Type.RPC_CALL.getValue());
out.writeInt(2); out.writeInt(2);
out.writeInt(program); out.writeInt(program);
out.writeInt(progVersion); out.writeInt(progVersion);
@ -105,7 +106,7 @@ public class RpcCall extends RpcMessage {
@Override @Override
public String toString() { public String toString() {
return String.format("Xid:%d, messageType:%d, rpcVersion:%d, program:%d," return String.format("Xid:%d, messageType:%s, rpcVersion:%d, program:%d,"
+ " version:%d, procedure:%d, credential:%s, verifier:%s", xid, + " version:%d, procedure:%d, credential:%s, verifier:%s", xid,
messageType, rpcVersion, program, version, procedure, messageType, rpcVersion, program, version, procedure,
credential.toString(), verifier.toString()); credential.toString(), verifier.toString());

View File

@ -25,16 +25,12 @@ import org.apache.hadoop.oncrpc.RpcAuthInfo.AuthFlavor;
*/ */
public class RpcDeniedReply extends RpcReply { public class RpcDeniedReply extends RpcReply {
public enum RejectState { public enum RejectState {
RPC_MISMATCH(0), AUTH_ERROR(1); // the order of the values below are significant.
RPC_MISMATCH,
private final int value; AUTH_ERROR;
RejectState(int value) {
this.value = value;
}
int getValue() { int getValue() {
return value; return ordinal();
} }
static RejectState fromValue(int value) { static RejectState fromValue(int value) {
@ -44,13 +40,13 @@ public class RpcDeniedReply extends RpcReply {
private final RejectState rejectState; private final RejectState rejectState;
RpcDeniedReply(int xid, int messageType, ReplyState replyState, RpcDeniedReply(int xid, RpcMessage.Type messageType, ReplyState replyState,
RejectState rejectState) { RejectState rejectState) {
super(xid, messageType, replyState); super(xid, messageType, replyState);
this.rejectState = rejectState; this.rejectState = rejectState;
} }
public static RpcDeniedReply read(int xid, int messageType, public static RpcDeniedReply read(int xid, RpcMessage.Type messageType,
ReplyState replyState, XDR xdr) { ReplyState replyState, XDR xdr) {
RejectState rejectState = RejectState.fromValue(xdr.readInt()); RejectState rejectState = RejectState.fromValue(xdr.readInt());
return new RpcDeniedReply(xid, messageType, replyState, rejectState); return new RpcDeniedReply(xid, messageType, replyState, rejectState);
@ -70,7 +66,7 @@ public class RpcDeniedReply extends RpcReply {
public static XDR voidReply(XDR xdr, int xid, ReplyState msgAccepted, public static XDR voidReply(XDR xdr, int xid, ReplyState msgAccepted,
RejectState rejectState) { RejectState rejectState) {
xdr.writeInt(xid); xdr.writeInt(xid);
xdr.writeInt(RpcMessage.RPC_REPLY); xdr.writeInt(RpcMessage.Type.RPC_REPLY.getValue());
xdr.writeInt(msgAccepted.getValue()); xdr.writeInt(msgAccepted.getValue());
xdr.writeInt(AuthFlavor.AUTH_NONE.getValue()); xdr.writeInt(AuthFlavor.AUTH_NONE.getValue());
xdr.writeVariableOpaque(new byte[0]); xdr.writeVariableOpaque(new byte[0]);

View File

@ -21,14 +21,29 @@ package org.apache.hadoop.oncrpc;
* Represent an RPC message as defined in RFC 1831. * Represent an RPC message as defined in RFC 1831.
*/ */
public abstract class RpcMessage { public abstract class RpcMessage {
public static final int RPC_CALL = 0; /** Message type */
public static final int RPC_REPLY = 1; public static enum Type {
// the order of the values below are significant.
RPC_CALL,
RPC_REPLY;
public int getValue() {
return ordinal();
}
public static Type fromValue(int value) {
if (value < 0 || value >= values().length) {
return null;
}
return values()[value];
}
}
protected final int xid; protected final int xid;
protected final int messageType; protected final Type messageType;
RpcMessage(int xid, int messageType) { RpcMessage(int xid, Type messageType) {
if (messageType != RPC_CALL && messageType != RPC_REPLY) { if (messageType != Type.RPC_CALL && messageType != Type.RPC_REPLY) {
throw new IllegalArgumentException("Invalid message type " + messageType); throw new IllegalArgumentException("Invalid message type " + messageType);
} }
this.xid = xid; this.xid = xid;
@ -39,11 +54,11 @@ public abstract class RpcMessage {
return xid; return xid;
} }
public int getMessageType() { public Type getMessageType() {
return messageType; return messageType;
} }
protected void validateMessageType(int expected) { protected void validateMessageType(Type expected) {
if (expected != messageType) { if (expected != messageType) {
throw new IllegalArgumentException("Message type is expected to be " throw new IllegalArgumentException("Message type is expected to be "
+ expected + " but got " + messageType); + expected + " but got " + messageType);

View File

@ -23,16 +23,12 @@ package org.apache.hadoop.oncrpc;
public abstract class RpcReply extends RpcMessage { public abstract class RpcReply extends RpcMessage {
/** RPC reply_stat as defined in RFC 1831 */ /** RPC reply_stat as defined in RFC 1831 */
public enum ReplyState { public enum ReplyState {
MSG_ACCEPTED(0), // the order of the values below are significant.
MSG_DENIED(1); MSG_ACCEPTED,
MSG_DENIED;
private final int value;
ReplyState(int value) {
this.value = value;
}
int getValue() { int getValue() {
return value; return ordinal();
} }
public static ReplyState fromValue(int value) { public static ReplyState fromValue(int value) {
@ -42,15 +38,15 @@ public abstract class RpcReply extends RpcMessage {
private final ReplyState state; private final ReplyState state;
RpcReply(int xid, int messageType, ReplyState state) { RpcReply(int xid, RpcMessage.Type messageType, ReplyState state) {
super(xid, messageType); super(xid, messageType);
this.state = state; this.state = state;
validateMessageType(RPC_REPLY); validateMessageType(RpcMessage.Type.RPC_REPLY);
} }
public static RpcReply read(XDR xdr) { public static RpcReply read(XDR xdr) {
int xid = xdr.readInt(); int xid = xdr.readInt();
int messageType = xdr.readInt(); final Type messageType = Type.fromValue(xdr.readInt());
ReplyState stat = ReplyState.fromValue(xdr.readInt()); ReplyState stat = ReplyState.fromValue(xdr.readInt());
switch (stat) { switch (stat) {
case MSG_ACCEPTED: case MSG_ACCEPTED:

View File

@ -25,28 +25,23 @@ import org.apache.hadoop.oncrpc.XDR;
*/ */
public interface PortmapInterface { public interface PortmapInterface {
public enum Procedure { public enum Procedure {
PMAPPROC_NULL(0), // the order of the values below are significant.
PMAPPROC_SET(1), PMAPPROC_NULL,
PMAPPROC_UNSET(2), PMAPPROC_SET,
PMAPPROC_GETPORT(3), PMAPPROC_UNSET,
PMAPPROC_DUMP(4), PMAPPROC_GETPORT,
PMAPPROC_CALLIT(5), PMAPPROC_DUMP,
PMAPPROC_GETTIME(6), PMAPPROC_CALLIT,
PMAPPROC_UADDR2TADDR(7), PMAPPROC_GETTIME,
PMAPPROC_TADDR2UADDR(8), PMAPPROC_UADDR2TADDR,
PMAPPROC_GETVERSADDR(9), PMAPPROC_TADDR2UADDR,
PMAPPROC_INDIRECT(10), PMAPPROC_GETVERSADDR,
PMAPPROC_GETADDRLIST(11), PMAPPROC_INDIRECT,
PMAPPROC_GETSTAT(12); PMAPPROC_GETADDRLIST,
PMAPPROC_GETSTAT;
private final int value;
Procedure(int value) {
this.value = value;
}
public int getValue() { public int getValue() {
return value; return ordinal();
} }
public static Procedure fromValue(int value) { public static Procedure fromValue(int value) {

View File

@ -46,10 +46,10 @@ public class TestRpcAcceptedReply {
@Test @Test
public void testConstructor() { public void testConstructor() {
RpcAuthInfo verifier = new RpcAuthInfo(AuthFlavor.AUTH_NONE, new byte[0]); RpcAuthInfo verifier = new RpcAuthInfo(AuthFlavor.AUTH_NONE, new byte[0]);
RpcAcceptedReply reply = new RpcAcceptedReply(0, RpcMessage.RPC_REPLY, RpcAcceptedReply reply = new RpcAcceptedReply(0, RpcMessage.Type.RPC_REPLY,
ReplyState.MSG_ACCEPTED, verifier, AcceptState.SUCCESS); ReplyState.MSG_ACCEPTED, verifier, AcceptState.SUCCESS);
assertEquals(0, reply.getXid()); assertEquals(0, reply.getXid());
assertEquals(RpcMessage.RPC_REPLY, reply.getMessageType()); assertEquals(RpcMessage.Type.RPC_REPLY, reply.getMessageType());
assertEquals(ReplyState.MSG_ACCEPTED, reply.getState()); assertEquals(ReplyState.MSG_ACCEPTED, reply.getState());
assertEquals(verifier, reply.getVerifier()); assertEquals(verifier, reply.getVerifier());
assertEquals(AcceptState.SUCCESS, reply.getAcceptState()); assertEquals(AcceptState.SUCCESS, reply.getAcceptState());

View File

@ -34,9 +34,10 @@ public class TestRpcCall {
int program = 2; int program = 2;
int version = 3; int version = 3;
int procedure = 4; int procedure = 4;
RpcCall call = new RpcCall(0, RpcMessage.RPC_CALL, rpcVersion, program, version, procedure, credential, verifier); RpcCall call = new RpcCall(0, RpcMessage.Type.RPC_CALL, rpcVersion, program,
version, procedure, credential, verifier);
assertEquals(0, call.getXid()); assertEquals(0, call.getXid());
assertEquals(RpcMessage.RPC_CALL, call.getMessageType()); assertEquals(RpcMessage.Type.RPC_CALL, call.getMessageType());
assertEquals(rpcVersion, call.getRpcVersion()); assertEquals(rpcVersion, call.getRpcVersion());
assertEquals(program, call.getProgram()); assertEquals(program, call.getProgram());
assertEquals(version, call.getVersion()); assertEquals(version, call.getVersion());
@ -48,12 +49,12 @@ public class TestRpcCall {
@Test(expected=IllegalArgumentException.class) @Test(expected=IllegalArgumentException.class)
public void testInvalidRpcVersion() { public void testInvalidRpcVersion() {
int invalidRpcVersion = 3; int invalidRpcVersion = 3;
new RpcCall(0, RpcMessage.RPC_CALL, invalidRpcVersion, 2, 3, 4, null, null); new RpcCall(0, RpcMessage.Type.RPC_CALL, invalidRpcVersion, 2, 3, 4, null, null);
} }
@Test(expected=IllegalArgumentException.class) @Test(expected=IllegalArgumentException.class)
public void testInvalidRpcMessageType() { public void testInvalidRpcMessageType() {
int invalidMessageType = 3; // Message typ is not RpcMessage.RPC_CALL RpcMessage.Type invalidMessageType = RpcMessage.Type.RPC_REPLY; // Message typ is not RpcMessage.RPC_CALL
new RpcCall(0, invalidMessageType, RpcCall.RPC_VERSION, 2, 3, 4, null, null); new RpcCall(0, invalidMessageType, RpcCall.RPC_VERSION, 2, 3, 4, null, null);
} }
} }

View File

@ -39,12 +39,12 @@ public class TestRpcDeniedReply {
@Test @Test
public void testConstructor() { public void testConstructor() {
RpcDeniedReply reply = new RpcDeniedReply(0, RpcMessage.RPC_REPLY, RpcDeniedReply reply = new RpcDeniedReply(0, RpcMessage.Type.RPC_REPLY,
ReplyState.MSG_ACCEPTED, RejectState.AUTH_ERROR) { ReplyState.MSG_ACCEPTED, RejectState.AUTH_ERROR) {
// Anonymous class // Anonymous class
}; };
Assert.assertEquals(0, reply.getXid()); Assert.assertEquals(0, reply.getXid());
Assert.assertEquals(RpcMessage.RPC_REPLY, reply.getMessageType()); Assert.assertEquals(RpcMessage.Type.RPC_REPLY, reply.getMessageType());
Assert.assertEquals(ReplyState.MSG_ACCEPTED, reply.getState()); Assert.assertEquals(ReplyState.MSG_ACCEPTED, reply.getState());
Assert.assertEquals(RejectState.AUTH_ERROR, reply.getRejectState()); Assert.assertEquals(RejectState.AUTH_ERROR, reply.getRejectState());
} }

View File

@ -24,34 +24,28 @@ import org.junit.Test;
* Test for {@link RpcMessage} * Test for {@link RpcMessage}
*/ */
public class TestRpcMessage { public class TestRpcMessage {
private RpcMessage getRpcMessage(int xid, int msgType) { private RpcMessage getRpcMessage(int xid, RpcMessage.Type msgType) {
return new RpcMessage(xid, msgType) { return new RpcMessage(xid, msgType) {
// Anonymous class // Anonymous class
}; };
} }
@Test(expected=IllegalArgumentException.class)
public void testInvalidMessageType() {
int invalidMsgType = 2; // valid values are 0 and 1
getRpcMessage(0, invalidMsgType);
}
@Test @Test
public void testRpcMessage() { public void testRpcMessage() {
RpcMessage msg = getRpcMessage(0, RpcMessage.RPC_CALL); RpcMessage msg = getRpcMessage(0, RpcMessage.Type.RPC_CALL);
Assert.assertEquals(0, msg.getXid()); Assert.assertEquals(0, msg.getXid());
Assert.assertEquals(RpcMessage.RPC_CALL, msg.getMessageType()); Assert.assertEquals(RpcMessage.Type.RPC_CALL, msg.getMessageType());
} }
@Test @Test
public void testValidateMessage() { public void testValidateMessage() {
RpcMessage msg = getRpcMessage(0, RpcMessage.RPC_CALL); RpcMessage msg = getRpcMessage(0, RpcMessage.Type.RPC_CALL);
msg.validateMessageType(RpcMessage.RPC_CALL); msg.validateMessageType(RpcMessage.Type.RPC_CALL);
} }
@Test(expected = IllegalArgumentException.class) @Test(expected = IllegalArgumentException.class)
public void testValidateMessageException() { public void testValidateMessageException() {
RpcMessage msg = getRpcMessage(0, RpcMessage.RPC_CALL); RpcMessage msg = getRpcMessage(0, RpcMessage.Type.RPC_CALL);
msg.validateMessageType(RpcMessage.RPC_REPLY); msg.validateMessageType(RpcMessage.Type.RPC_REPLY);
} }
} }

View File

@ -39,11 +39,11 @@ public class TestRpcReply {
@Test @Test
public void testRpcReply() { public void testRpcReply() {
RpcReply reply = new RpcReply(0, 1, ReplyState.MSG_ACCEPTED) { RpcReply reply = new RpcReply(0, RpcMessage.Type.RPC_REPLY, ReplyState.MSG_ACCEPTED) {
// Anonymous class // Anonymous class
}; };
Assert.assertEquals(0, reply.getXid()); Assert.assertEquals(0, reply.getXid());
Assert.assertEquals(1, reply.getMessageType()); Assert.assertEquals(RpcMessage.Type.RPC_REPLY, reply.getMessageType());
Assert.assertEquals(ReplyState.MSG_ACCEPTED, reply.getState()); Assert.assertEquals(ReplyState.MSG_ACCEPTED, reply.getState());
} }
} }

View File

@ -154,24 +154,25 @@ public class RpcProgramMountd extends RpcProgram implements MountInterface {
@Override @Override
public XDR handleInternal(RpcCall rpcCall, XDR xdr, XDR out, public XDR handleInternal(RpcCall rpcCall, XDR xdr, XDR out,
InetAddress client, Channel channel) { InetAddress client, Channel channel) {
int procedure = rpcCall.getProcedure(); final MNTPROC mntproc = MNTPROC.fromValue(rpcCall.getProcedure());
int xid = rpcCall.getXid(); int xid = rpcCall.getXid();
if (procedure == MNTPROC_NULL) { if (mntproc == MNTPROC.NULL) {
out = nullOp(out, xid, client); out = nullOp(out, xid, client);
} else if (procedure == MNTPROC_MNT) { } else if (mntproc == MNTPROC.MNT) {
out = mnt(xdr, out, xid, client); out = mnt(xdr, out, xid, client);
} else if (procedure == MNTPROC_DUMP) { } else if (mntproc == MNTPROC.DUMP) {
out = dump(out, xid, client); out = dump(out, xid, client);
} else if (procedure == MNTPROC_UMNT) { } else if (mntproc == MNTPROC.UMNT) {
out = umnt(xdr, out, xid, client); out = umnt(xdr, out, xid, client);
} else if (procedure == MNTPROC_UMNTALL) { } else if (mntproc == MNTPROC.UMNTALL) {
umntall(out, xid, client); umntall(out, xid, client);
} else if (procedure == MNTPROC_EXPORT) { } else if (mntproc == MNTPROC.EXPORT) {
out = MountResponse.writeExportList(out, xid, exports); out = MountResponse.writeExportList(out, xid, exports);
} else { } else {
// Invalid procedure // Invalid procedure
RpcAcceptedReply.voidReply(out, xid, RpcAcceptedReply.voidReply(out, xid,
RpcAcceptedReply.AcceptState.PROC_UNAVAIL); } RpcAcceptedReply.AcceptState.PROC_UNAVAIL);
}
return out; return out;
} }

View File

@ -36,6 +36,7 @@ import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.hdfs.DFSClient; import org.apache.hadoop.hdfs.DFSClient;
import org.apache.hadoop.hdfs.client.HdfsDataOutputStream; import org.apache.hadoop.hdfs.client.HdfsDataOutputStream;
import org.apache.hadoop.hdfs.client.HdfsDataOutputStream.SyncFlag; import org.apache.hadoop.hdfs.client.HdfsDataOutputStream.SyncFlag;
import org.apache.hadoop.hdfs.nfs.nfs3.WriteCtx.DataState;
import org.apache.hadoop.io.BytesWritable.Comparator; import org.apache.hadoop.io.BytesWritable.Comparator;
import org.apache.hadoop.io.IOUtils; import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.nfs.nfs3.FileHandle; import org.apache.hadoop.nfs.nfs3.FileHandle;
@ -345,7 +346,7 @@ class OpenFileCtx {
+ " nextOffset:" + nextOffset); + " nextOffset:" + nextOffset);
WriteCtx writeCtx = new WriteCtx(request.getHandle(), WriteCtx writeCtx = new WriteCtx(request.getHandle(),
request.getOffset(), request.getCount(), request.getStableHow(), request.getOffset(), request.getCount(), request.getStableHow(),
request.getData().array(), channel, xid, false, WriteCtx.NO_DUMP); request.getData().array(), channel, xid, false, DataState.NO_DUMP);
addWrite(writeCtx); addWrite(writeCtx);
// Create an async task and change openFileCtx status to indicate async // Create an async task and change openFileCtx status to indicate async
@ -373,7 +374,7 @@ class OpenFileCtx {
+ nextOffset); + nextOffset);
WriteCtx writeCtx = new WriteCtx(request.getHandle(), WriteCtx writeCtx = new WriteCtx(request.getHandle(),
request.getOffset(), request.getCount(), request.getStableHow(), request.getOffset(), request.getCount(), request.getStableHow(),
request.getData().array(), channel, xid, false, WriteCtx.ALLOW_DUMP); request.getData().array(), channel, xid, false, DataState.ALLOW_DUMP);
addWrite(writeCtx); addWrite(writeCtx);
// Check if need to dump some pending requests to file // Check if need to dump some pending requests to file
@ -699,7 +700,7 @@ class OpenFileCtx {
nextOffset = fos.getPos(); nextOffset = fos.getPos();
// Reduce memory occupation size if request was allowed dumped // Reduce memory occupation size if request was allowed dumped
if (writeCtx.getDataState() == WriteCtx.ALLOW_DUMP) { if (writeCtx.getDataState() == DataState.ALLOW_DUMP) {
updateNonSequentialWriteInMemory(-count); updateNonSequentialWriteInMemory(-count);
} }

View File

@ -46,6 +46,7 @@ import org.apache.hadoop.nfs.NfsTime;
import org.apache.hadoop.nfs.nfs3.FileHandle; import org.apache.hadoop.nfs.nfs3.FileHandle;
import org.apache.hadoop.nfs.nfs3.IdUserGroup; import org.apache.hadoop.nfs.nfs3.IdUserGroup;
import org.apache.hadoop.nfs.nfs3.Nfs3Constant; import org.apache.hadoop.nfs.nfs3.Nfs3Constant;
import org.apache.hadoop.nfs.nfs3.Nfs3Constant.NFSPROC3;
import org.apache.hadoop.nfs.nfs3.Nfs3Constant.WriteStableHow; import org.apache.hadoop.nfs.nfs3.Nfs3Constant.WriteStableHow;
import org.apache.hadoop.nfs.nfs3.Nfs3FileAttributes; import org.apache.hadoop.nfs.nfs3.Nfs3FileAttributes;
import org.apache.hadoop.nfs.nfs3.Nfs3Interface; import org.apache.hadoop.nfs.nfs3.Nfs3Interface;
@ -1530,12 +1531,12 @@ public class RpcProgramNfs3 extends RpcProgram implements Nfs3Interface {
@Override @Override
public XDR handleInternal(RpcCall rpcCall, final XDR xdr, XDR out, public XDR handleInternal(RpcCall rpcCall, final XDR xdr, XDR out,
InetAddress client, Channel channel) { InetAddress client, Channel channel) {
int procedure = rpcCall.getProcedure(); final NFSPROC3 nfsproc3 = NFSPROC3.fromValue(rpcCall.getProcedure());
int xid = rpcCall.getXid(); int xid = rpcCall.getXid();
RpcAuthSys authSys = null; RpcAuthSys authSys = null;
// Ignore auth only for NFSPROC3_NULL, especially for Linux clients. // Ignore auth only for NFSPROC3_NULL, especially for Linux clients.
if (procedure != Nfs3Constant.NFSPROC3_NULL) { if (nfsproc3 != NFSPROC3.NULL) {
if (rpcCall.getCredential().getFlavor() != AuthFlavor.AUTH_SYS) { if (rpcCall.getCredential().getFlavor() != AuthFlavor.AUTH_SYS) {
LOG.info("Wrong RPC AUTH flavor, " LOG.info("Wrong RPC AUTH flavor, "
+ rpcCall.getCredential().getFlavor() + " is not AUTH_SYS."); + rpcCall.getCredential().getFlavor() + " is not AUTH_SYS.");
@ -1549,49 +1550,49 @@ public class RpcProgramNfs3 extends RpcProgram implements Nfs3Interface {
} }
NFS3Response response = null; NFS3Response response = null;
if (procedure == Nfs3Constant.NFSPROC3_NULL) { if (nfsproc3 == NFSPROC3.NULL) {
response = nullProcedure(); response = nullProcedure();
} else if (procedure == Nfs3Constant.NFSPROC3_GETATTR) { } else if (nfsproc3 == NFSPROC3.GETATTR) {
response = getattr(xdr, authSys); response = getattr(xdr, authSys);
} else if (procedure == Nfs3Constant.NFSPROC3_SETATTR) { } else if (nfsproc3 == NFSPROC3.SETATTR) {
response = setattr(xdr, authSys); response = setattr(xdr, authSys);
} else if (procedure == Nfs3Constant.NFSPROC3_LOOKUP) { } else if (nfsproc3 == NFSPROC3.LOOKUP) {
response = lookup(xdr, authSys); response = lookup(xdr, authSys);
} else if (procedure == Nfs3Constant.NFSPROC3_ACCESS) { } else if (nfsproc3 == NFSPROC3.ACCESS) {
response = access(xdr, authSys); response = access(xdr, authSys);
} else if (procedure == Nfs3Constant.NFSPROC3_READLINK) { } else if (nfsproc3 == NFSPROC3.READLINK) {
response = readlink(xdr, authSys); response = readlink(xdr, authSys);
} else if (procedure == Nfs3Constant.NFSPROC3_READ) { } else if (nfsproc3 == NFSPROC3.READ) {
response = read(xdr, authSys); response = read(xdr, authSys);
} else if (procedure == Nfs3Constant.NFSPROC3_WRITE) { } else if (nfsproc3 == NFSPROC3.WRITE) {
response = write(xdr, channel, xid, authSys); response = write(xdr, channel, xid, authSys);
} else if (procedure == Nfs3Constant.NFSPROC3_CREATE) { } else if (nfsproc3 == NFSPROC3.CREATE) {
response = create(xdr, authSys); response = create(xdr, authSys);
} else if (procedure == Nfs3Constant.NFSPROC3_MKDIR) { } else if (nfsproc3 == NFSPROC3.MKDIR) {
response = mkdir(xdr, authSys); response = mkdir(xdr, authSys);
} else if (procedure == Nfs3Constant.NFSPROC3_SYMLINK) { } else if (nfsproc3 == NFSPROC3.SYMLINK) {
response = symlink(xdr, authSys); response = symlink(xdr, authSys);
} else if (procedure == Nfs3Constant.NFSPROC3_MKNOD) { } else if (nfsproc3 == NFSPROC3.MKNOD) {
response = mknod(xdr, authSys); response = mknod(xdr, authSys);
} else if (procedure == Nfs3Constant.NFSPROC3_REMOVE) { } else if (nfsproc3 == NFSPROC3.REMOVE) {
response = remove(xdr, authSys); response = remove(xdr, authSys);
} else if (procedure == Nfs3Constant.NFSPROC3_RMDIR) { } else if (nfsproc3 == NFSPROC3.RMDIR) {
response = rmdir(xdr, authSys); response = rmdir(xdr, authSys);
} else if (procedure == Nfs3Constant.NFSPROC3_RENAME) { } else if (nfsproc3 == NFSPROC3.RENAME) {
response = rename(xdr, authSys); response = rename(xdr, authSys);
} else if (procedure == Nfs3Constant.NFSPROC3_LINK) { } else if (nfsproc3 == NFSPROC3.LINK) {
response = link(xdr, authSys); response = link(xdr, authSys);
} else if (procedure == Nfs3Constant.NFSPROC3_READDIR) { } else if (nfsproc3 == NFSPROC3.READDIR) {
response = readdir(xdr, authSys); response = readdir(xdr, authSys);
} else if (procedure == Nfs3Constant.NFSPROC3_READDIRPLUS) { } else if (nfsproc3 == NFSPROC3.READDIRPLUS) {
response = readdirplus(xdr, authSys); response = readdirplus(xdr, authSys);
} else if (procedure == Nfs3Constant.NFSPROC3_FSSTAT) { } else if (nfsproc3 == NFSPROC3.FSSTAT) {
response = fsstat(xdr, authSys); response = fsstat(xdr, authSys);
} else if (procedure == Nfs3Constant.NFSPROC3_FSINFO) { } else if (nfsproc3 == NFSPROC3.FSINFO) {
response = fsinfo(xdr, authSys); response = fsinfo(xdr, authSys);
} else if (procedure == Nfs3Constant.NFSPROC3_PATHCONF) { } else if (nfsproc3 == NFSPROC3.PATHCONF) {
response = pathconf(xdr, authSys); response = pathconf(xdr, authSys);
} else if (procedure == Nfs3Constant.NFSPROC3_COMMIT) { } else if (nfsproc3 == NFSPROC3.COMMIT) {
response = commit(xdr, authSys); response = commit(xdr, authSys);
} else { } else {
// Invalid procedure // Invalid procedure
@ -1606,17 +1607,7 @@ public class RpcProgramNfs3 extends RpcProgram implements Nfs3Interface {
@Override @Override
protected boolean isIdempotent(RpcCall call) { protected boolean isIdempotent(RpcCall call) {
return isIdempotent(call.getProcedure()); final NFSPROC3 nfsproc3 = NFSPROC3.fromValue(call.getProcedure());
} return nfsproc3 == null || nfsproc3.isIdempotent();
public static boolean isIdempotent(int procedure) {
return !(procedure == Nfs3Constant.NFSPROC3_CREATE
|| procedure == Nfs3Constant.NFSPROC3_REMOVE
|| procedure == Nfs3Constant.NFSPROC3_MKDIR
|| procedure == Nfs3Constant.NFSPROC3_MKNOD
|| procedure == Nfs3Constant.NFSPROC3_LINK
|| procedure == Nfs3Constant.NFSPROC3_RMDIR
|| procedure == Nfs3Constant.NFSPROC3_SYMLINK
|| procedure == Nfs3Constant.NFSPROC3_RENAME);
} }
} }

View File

@ -33,6 +33,17 @@ import org.jboss.netty.channel.Channel;
*/ */
class WriteCtx { class WriteCtx {
public static final Log LOG = LogFactory.getLog(WriteCtx.class); public static final Log LOG = LogFactory.getLog(WriteCtx.class);
/**
* In memory write data has 3 states. ALLOW_DUMP: not sequential write, still
* wait for prerequisit writes. NO_DUMP: sequential write, no need to dump
* since it will be written to HDFS soon. DUMPED: already dumped to a file.
*/
public static enum DataState {
ALLOW_DUMP,
NO_DUMP,
DUMPED;
}
private final FileHandle handle; private final FileHandle handle;
private final long offset; private final long offset;
@ -43,22 +54,14 @@ class WriteCtx {
private final Channel channel; private final Channel channel;
private final int xid; private final int xid;
private boolean replied; private boolean replied;
/**
* In memory write data has 3 states. ALLOW_DUMP: not sequential write, still
* wait for prerequisit writes. NO_DUMP: sequential write, no need to dump
* since it will be written to HDFS soon. DUMPED: already dumped to a file.
*/
public final static int ALLOW_DUMP = 0;
public final static int NO_DUMP = 1;
public final static int DUMPED = 2;
private int dataState;
public int getDataState() { private DataState dataState;
public DataState getDataState() {
return dataState; return dataState;
} }
public void setDataState(int dataState) { public void setDataState(DataState dataState) {
this.dataState = dataState; this.dataState = dataState;
} }
@ -68,7 +71,7 @@ class WriteCtx {
// Return the dumped data size // Return the dumped data size
public long dumpData(FileOutputStream dumpOut, RandomAccessFile raf) public long dumpData(FileOutputStream dumpOut, RandomAccessFile raf)
throws IOException { throws IOException {
if (dataState != ALLOW_DUMP) { if (dataState != DataState.ALLOW_DUMP) {
if (LOG.isTraceEnabled()) { if (LOG.isTraceEnabled()) {
LOG.trace("No need to dump with status(replied,dataState):" + "(" LOG.trace("No need to dump with status(replied,dataState):" + "("
+ replied + "," + dataState + ")"); + replied + "," + dataState + ")");
@ -82,7 +85,7 @@ class WriteCtx {
LOG.debug("After dump, new dumpFileOffset:" + dumpFileOffset); LOG.debug("After dump, new dumpFileOffset:" + dumpFileOffset);
} }
data = null; data = null;
dataState = DUMPED; dataState = DataState.DUMPED;
return count; return count;
} }
@ -103,7 +106,7 @@ class WriteCtx {
} }
public byte[] getData() throws IOException { public byte[] getData() throws IOException {
if (dataState != DUMPED) { if (dataState != DataState.DUMPED) {
if (data == null) { if (data == null) {
throw new IOException("Data is not dumpted but has null:" + this); throw new IOException("Data is not dumpted but has null:" + this);
} }
@ -140,7 +143,7 @@ class WriteCtx {
} }
WriteCtx(FileHandle handle, long offset, int count, WriteStableHow stableHow, WriteCtx(FileHandle handle, long offset, int count, WriteStableHow stableHow,
byte[] data, Channel channel, int xid, boolean replied, int dataState) { byte[] data, Channel channel, int xid, boolean replied, DataState dataState) {
this.handle = handle; this.handle = handle;
this.offset = offset; this.offset = offset;
this.count = count; this.count = count;

View File

@ -59,7 +59,7 @@ public class TestOutOfOrderWrite {
static XDR create() { static XDR create() {
XDR request = new XDR(); XDR request = new XDR();
RpcCall.write(request, 0x8000004c, Nfs3Constant.PROGRAM, RpcCall.write(request, 0x8000004c, Nfs3Constant.PROGRAM,
Nfs3Constant.VERSION, Nfs3Constant.NFSPROC3_CREATE); Nfs3Constant.VERSION, Nfs3Constant.NFSPROC3.CREATE.getValue());
// credentials // credentials
request.writeInt(0); // auth null request.writeInt(0); // auth null
@ -79,7 +79,7 @@ public class TestOutOfOrderWrite {
byte[] data) { byte[] data) {
XDR request = new XDR(); XDR request = new XDR();
RpcCall.write(request, xid, Nfs3Constant.PROGRAM, Nfs3Constant.VERSION, RpcCall.write(request, xid, Nfs3Constant.PROGRAM, Nfs3Constant.VERSION,
Nfs3Constant.NFSPROC3_WRITE); Nfs3Constant.NFSPROC3.WRITE.getValue());
// credentials // credentials
request.writeInt(0); // auth null request.writeInt(0); // auth null

View File

@ -28,38 +28,38 @@ import org.junit.Test;
public class TestRpcProgramNfs3 { public class TestRpcProgramNfs3 {
@Test(timeout=1000) @Test(timeout=1000)
public void testIdempotent() { public void testIdempotent() {
int[][] procedures = { Object[][] procedures = {
{ Nfs3Constant.NFSPROC3_NULL, 1 }, { Nfs3Constant.NFSPROC3.NULL, 1 },
{ Nfs3Constant.NFSPROC3_GETATTR, 1 }, { Nfs3Constant.NFSPROC3.GETATTR, 1 },
{ Nfs3Constant.NFSPROC3_SETATTR, 1 }, { Nfs3Constant.NFSPROC3.SETATTR, 1 },
{ Nfs3Constant.NFSPROC3_LOOKUP, 1 }, { Nfs3Constant.NFSPROC3.LOOKUP, 1 },
{ Nfs3Constant.NFSPROC3_ACCESS, 1 }, { Nfs3Constant.NFSPROC3.ACCESS, 1 },
{ Nfs3Constant.NFSPROC3_READLINK, 1 }, { Nfs3Constant.NFSPROC3.READLINK, 1 },
{ Nfs3Constant.NFSPROC3_READ, 1 }, { Nfs3Constant.NFSPROC3.READ, 1 },
{ Nfs3Constant.NFSPROC3_WRITE, 1 }, { Nfs3Constant.NFSPROC3.WRITE, 1 },
{ Nfs3Constant.NFSPROC3_CREATE, 0 }, { Nfs3Constant.NFSPROC3.CREATE, 0 },
{ Nfs3Constant.NFSPROC3_MKDIR, 0 }, { Nfs3Constant.NFSPROC3.MKDIR, 0 },
{ Nfs3Constant.NFSPROC3_SYMLINK, 0 }, { Nfs3Constant.NFSPROC3.SYMLINK, 0 },
{ Nfs3Constant.NFSPROC3_MKNOD, 0 }, { Nfs3Constant.NFSPROC3.MKNOD, 0 },
{ Nfs3Constant.NFSPROC3_REMOVE, 0 }, { Nfs3Constant.NFSPROC3.REMOVE, 0 },
{ Nfs3Constant.NFSPROC3_RMDIR, 0 }, { Nfs3Constant.NFSPROC3.RMDIR, 0 },
{ Nfs3Constant.NFSPROC3_RENAME, 0 }, { Nfs3Constant.NFSPROC3.RENAME, 0 },
{ Nfs3Constant.NFSPROC3_LINK, 0 }, { Nfs3Constant.NFSPROC3.LINK, 0 },
{ Nfs3Constant.NFSPROC3_READDIR, 1 }, { Nfs3Constant.NFSPROC3.READDIR, 1 },
{ Nfs3Constant.NFSPROC3_READDIRPLUS, 1 }, { Nfs3Constant.NFSPROC3.READDIRPLUS, 1 },
{ Nfs3Constant.NFSPROC3_FSSTAT, 1 }, { Nfs3Constant.NFSPROC3.FSSTAT, 1 },
{ Nfs3Constant.NFSPROC3_FSINFO, 1 }, { Nfs3Constant.NFSPROC3.FSINFO, 1 },
{ Nfs3Constant.NFSPROC3_PATHCONF, 1 }, { Nfs3Constant.NFSPROC3.PATHCONF, 1 },
{ Nfs3Constant.NFSPROC3_COMMIT, 1 } }; { Nfs3Constant.NFSPROC3.COMMIT, 1 } };
for (int[] procedure : procedures) { for (Object[] procedure : procedures) {
boolean idempotent = procedure[1] == 1; boolean idempotent = procedure[1].equals(Integer.valueOf(1));
int proc = procedure[0]; Nfs3Constant.NFSPROC3 proc = (Nfs3Constant.NFSPROC3)procedure[0];
if (idempotent) { if (idempotent) {
Assert.assertTrue(("Procedure " + proc + " should be idempotent"), Assert.assertTrue(("Procedure " + proc + " should be idempotent"),
RpcProgramNfs3.isIdempotent(proc)); proc.isIdempotent());
} else { } else {
Assert.assertFalse(("Procedure " + proc + " should be non-idempotent"), Assert.assertFalse(("Procedure " + proc + " should be non-idempotent"),
RpcProgramNfs3.isIdempotent(proc)); proc.isIdempotent());
} }
} }
} }

View File

@ -18,6 +18,8 @@ Release 2.3.0 - UNRELEASED
NEW FEATURES NEW FEATURES
HDFS-4962 Use enum for nfs constants (Nicholas SZE via jing9)
IMPROVEMENTS IMPROVEMENTS
HDFS-4657. Limit the number of blocks logged by the NN after a block HDFS-4657. Limit the number of blocks logged by the NN after a block