|
@@ -986,9 +986,7 @@ class BlockReceiver implements Closeable {
|
|
private static enum PacketResponderType {
|
|
private static enum PacketResponderType {
|
|
NON_PIPELINE, LAST_IN_PIPELINE, HAS_DOWNSTREAM_IN_PIPELINE
|
|
NON_PIPELINE, LAST_IN_PIPELINE, HAS_DOWNSTREAM_IN_PIPELINE
|
|
}
|
|
}
|
|
-
|
|
|
|
- private static final Status[] MIRROR_ERROR_STATUS = {Status.SUCCESS, Status.ERROR};
|
|
|
|
-
|
|
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* Processes responses from downstream datanodes in the pipeline
|
|
* Processes responses from downstream datanodes in the pipeline
|
|
* and sends back replies to the originator.
|
|
* and sends back replies to the originator.
|
|
@@ -1092,7 +1090,7 @@ class BlockReceiver implements Closeable {
|
|
LOG.info("Sending an out of band ack of type " + ackStatus);
|
|
LOG.info("Sending an out of band ack of type " + ackStatus);
|
|
try {
|
|
try {
|
|
sendAckUpstreamUnprotected(null, PipelineAck.UNKOWN_SEQNO, 0L, 0L,
|
|
sendAckUpstreamUnprotected(null, PipelineAck.UNKOWN_SEQNO, 0L, 0L,
|
|
- ackStatus);
|
|
|
|
|
|
+ PipelineAck.combineHeader(datanode.getECN(), ackStatus));
|
|
} finally {
|
|
} finally {
|
|
// Let others send ack. Unless there are miltiple OOB send
|
|
// Let others send ack. Unless there are miltiple OOB send
|
|
// calls, there can be only one waiter, the responder thread.
|
|
// calls, there can be only one waiter, the responder thread.
|
|
@@ -1175,7 +1173,8 @@ class BlockReceiver implements Closeable {
|
|
if (oobStatus != null) {
|
|
if (oobStatus != null) {
|
|
LOG.info("Relaying an out of band ack of type " + oobStatus);
|
|
LOG.info("Relaying an out of band ack of type " + oobStatus);
|
|
sendAckUpstream(ack, PipelineAck.UNKOWN_SEQNO, 0L, 0L,
|
|
sendAckUpstream(ack, PipelineAck.UNKOWN_SEQNO, 0L, 0L,
|
|
- Status.SUCCESS);
|
|
|
|
|
|
+ PipelineAck.combineHeader(datanode.getECN(),
|
|
|
|
+ Status.SUCCESS));
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
seqno = ack.getSeqno();
|
|
seqno = ack.getSeqno();
|
|
@@ -1249,9 +1248,10 @@ class BlockReceiver implements Closeable {
|
|
finalizeBlock(startTime);
|
|
finalizeBlock(startTime);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ Status myStatus = pkt != null ? pkt.ackStatus : Status.SUCCESS;
|
|
sendAckUpstream(ack, expected, totalAckTimeNanos,
|
|
sendAckUpstream(ack, expected, totalAckTimeNanos,
|
|
- (pkt != null ? pkt.offsetInBlock : 0),
|
|
|
|
- (pkt != null ? pkt.ackStatus : Status.SUCCESS));
|
|
|
|
|
|
+ (pkt != null ? pkt.offsetInBlock : 0),
|
|
|
|
+ PipelineAck.combineHeader(datanode.getECN(), myStatus));
|
|
if (pkt != null) {
|
|
if (pkt != null) {
|
|
// remove the packet from the ack queue
|
|
// remove the packet from the ack queue
|
|
removeAckHead();
|
|
removeAckHead();
|
|
@@ -1311,11 +1311,11 @@ class BlockReceiver implements Closeable {
|
|
* @param totalAckTimeNanos total ack time including all the downstream
|
|
* @param totalAckTimeNanos total ack time including all the downstream
|
|
* nodes
|
|
* nodes
|
|
* @param offsetInBlock offset in block for the data in packet
|
|
* @param offsetInBlock offset in block for the data in packet
|
|
- * @param myStatus the local ack status
|
|
|
|
|
|
+ * @param myHeader the local ack header
|
|
*/
|
|
*/
|
|
private void sendAckUpstream(PipelineAck ack, long seqno,
|
|
private void sendAckUpstream(PipelineAck ack, long seqno,
|
|
long totalAckTimeNanos, long offsetInBlock,
|
|
long totalAckTimeNanos, long offsetInBlock,
|
|
- Status myStatus) throws IOException {
|
|
|
|
|
|
+ int myHeader) throws IOException {
|
|
try {
|
|
try {
|
|
// Wait for other sender to finish. Unless there is an OOB being sent,
|
|
// Wait for other sender to finish. Unless there is an OOB being sent,
|
|
// the responder won't have to wait.
|
|
// the responder won't have to wait.
|
|
@@ -1329,7 +1329,7 @@ class BlockReceiver implements Closeable {
|
|
try {
|
|
try {
|
|
if (!running) return;
|
|
if (!running) return;
|
|
sendAckUpstreamUnprotected(ack, seqno, totalAckTimeNanos,
|
|
sendAckUpstreamUnprotected(ack, seqno, totalAckTimeNanos,
|
|
- offsetInBlock, myStatus);
|
|
|
|
|
|
+ offsetInBlock, myHeader);
|
|
} finally {
|
|
} finally {
|
|
synchronized(this) {
|
|
synchronized(this) {
|
|
sending = false;
|
|
sending = false;
|
|
@@ -1349,32 +1349,34 @@ class BlockReceiver implements Closeable {
|
|
* @param totalAckTimeNanos total ack time including all the downstream
|
|
* @param totalAckTimeNanos total ack time including all the downstream
|
|
* nodes
|
|
* nodes
|
|
* @param offsetInBlock offset in block for the data in packet
|
|
* @param offsetInBlock offset in block for the data in packet
|
|
- * @param myStatus the local ack status
|
|
|
|
|
|
+ * @param myHeader the local ack header
|
|
*/
|
|
*/
|
|
private void sendAckUpstreamUnprotected(PipelineAck ack, long seqno,
|
|
private void sendAckUpstreamUnprotected(PipelineAck ack, long seqno,
|
|
- long totalAckTimeNanos, long offsetInBlock, Status myStatus)
|
|
|
|
|
|
+ long totalAckTimeNanos, long offsetInBlock, int myHeader)
|
|
throws IOException {
|
|
throws IOException {
|
|
- Status[] replies = null;
|
|
|
|
|
|
+ final int[] replies;
|
|
if (ack == null) {
|
|
if (ack == null) {
|
|
// A new OOB response is being sent from this node. Regardless of
|
|
// A new OOB response is being sent from this node. Regardless of
|
|
// downstream nodes, reply should contain one reply.
|
|
// downstream nodes, reply should contain one reply.
|
|
- replies = new Status[1];
|
|
|
|
- replies[0] = myStatus;
|
|
|
|
|
|
+ replies = new int[] { myHeader };
|
|
} else if (mirrorError) { // ack read error
|
|
} else if (mirrorError) { // ack read error
|
|
- replies = MIRROR_ERROR_STATUS;
|
|
|
|
|
|
+ int h = PipelineAck.combineHeader(datanode.getECN(), Status.SUCCESS);
|
|
|
|
+ int h1 = PipelineAck.combineHeader(datanode.getECN(), Status.ERROR);
|
|
|
|
+ replies = new int[] {h, h1};
|
|
} else {
|
|
} else {
|
|
short ackLen = type == PacketResponderType.LAST_IN_PIPELINE ? 0 : ack
|
|
short ackLen = type == PacketResponderType.LAST_IN_PIPELINE ? 0 : ack
|
|
.getNumOfReplies();
|
|
.getNumOfReplies();
|
|
- replies = new Status[1 + ackLen];
|
|
|
|
- replies[0] = myStatus;
|
|
|
|
- for (int i = 0; i < ackLen; i++) {
|
|
|
|
|
|
+ replies = new int[ackLen + 1];
|
|
|
|
+ replies[0] = myHeader;
|
|
|
|
+ for (int i = 0; i < ackLen; ++i) {
|
|
replies[i + 1] = ack.getReply(i);
|
|
replies[i + 1] = ack.getReply(i);
|
|
}
|
|
}
|
|
// If the mirror has reported that it received a corrupt packet,
|
|
// If the mirror has reported that it received a corrupt packet,
|
|
- // do self-destruct to mark myself bad, instead of making the
|
|
|
|
|
|
+ // do self-destruct to mark myself bad, instead of making the
|
|
// mirror node bad. The mirror is guaranteed to be good without
|
|
// mirror node bad. The mirror is guaranteed to be good without
|
|
// corrupt data on disk.
|
|
// corrupt data on disk.
|
|
- if (ackLen > 0 && replies[1] == Status.ERROR_CHECKSUM) {
|
|
|
|
|
|
+ if (ackLen > 0 && PipelineAck.getStatusFromHeader(replies[1]) ==
|
|
|
|
+ Status.ERROR_CHECKSUM) {
|
|
throw new IOException("Shutting down writer and responder "
|
|
throw new IOException("Shutting down writer and responder "
|
|
+ "since the down streams reported the data sent by this "
|
|
+ "since the down streams reported the data sent by this "
|
|
+ "thread is corrupt");
|
|
+ "thread is corrupt");
|
|
@@ -1400,7 +1402,8 @@ class BlockReceiver implements Closeable {
|
|
}
|
|
}
|
|
|
|
|
|
// If a corruption was detected in the received data, terminate after
|
|
// If a corruption was detected in the received data, terminate after
|
|
- // sending ERROR_CHECKSUM back.
|
|
|
|
|
|
+ // sending ERROR_CHECKSUM back.
|
|
|
|
+ Status myStatus = PipelineAck.getStatusFromHeader(myHeader);
|
|
if (myStatus == Status.ERROR_CHECKSUM) {
|
|
if (myStatus == Status.ERROR_CHECKSUM) {
|
|
throw new IOException("Shutting down writer and responder "
|
|
throw new IOException("Shutting down writer and responder "
|
|
+ "due to a checksum error in received data. The error "
|
|
+ "due to a checksum error in received data. The error "
|
|
@@ -1420,7 +1423,7 @@ class BlockReceiver implements Closeable {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* This information is cached by the Datanode in the ackQueue.
|
|
* This information is cached by the Datanode in the ackQueue.
|
|
*/
|
|
*/
|