在《HDFS源码分析DataXceiver之整体流程》一文中我们知道,无论来自客户端还是其他数据节点的请求达到DataNode时,DataNode上的后台线程DataXceiverServer均为每个请求创建一个单独的后台工作线程来处理,这个工作线程就是DataXceiver。并且,在线程DataXceiver处理请求的主方法run()方法内,会先读取操作符op,然后根据操作符op分别调用相应的方法进行请求的处理。而决定什么样的操作符op该调用何种方法的逻辑,则是在DataXceiver线程父类Receiver的processOp()方法中实现的,代码如下:
/** Process op by the corresponding method. */
protected final void processOp(Op op) throws IOException {
// 通过调用相应的方法处理操作符
switch(op) {
case READ_BLOCK:// 读数据块调用opReadBlock()方法
opReadBlock();
break;
case WRITE_BLOCK:// 写数据块调用opWriteBlock()方法
opWriteBlock(in);
break;
case REPLACE_BLOCK:// 替换数据块调用opReplaceBlock()方法
opReplaceBlock(in);
break;
case COPY_BLOCK:// 复制数据块调用REPLACE()方法
opCopyBlock(in);
break;
case BLOCK_CHECKSUM:// 数据块检验调用opBlockChecksum()方法
opBlockChecksum(in);
break;
case TRANSFER_BLOCK:// 移动数据块调用opTransferBlock()方法
opTransferBlock(in);
break;
case REQUEST_SHORT_CIRCUIT_FDS:
opRequestShortCircuitFds(in);
break;
case RELEASE_SHORT_CIRCUIT_FDS:
opReleaseShortCircuitFds(in);
break;
case REQUEST_SHORT_CIRCUIT_SHM:
opRequestShortCircuitShm(in);
break;
default:
throw new IOException("Unknown op " + op + " in data stream");
}
}
接下来的几篇文章,我们将依次为大家介绍读数据块、写数据块、替换数据块、复制数据块、移动数据块等具体数据读写请求的处理。
那么今天,我们首先来看下第一种数据读写请求--读数据块READ_BLOCK,它是通过调用opReadBlock()方法完成的,我们先看下这个方法的代码:
/** Receive OP_READ_BLOCK */
private void opReadBlock() throws IOException {
// 解析输入流,得到读数据块消息协议OpReadBlockProto,即proto
OpReadBlockProto proto = OpReadBlockProto.parseFrom(vintPrefixed(in));
// 创建TraceScope类型的traceScope
TraceScope traceScope = continueTraceSpan(proto.getHeader(),
proto.getClass().getSimpleName());
try {
// 调用readBlock()方法,完成读数据块操作
// 从读数据块消息协议OpReadBlockProto中分别获得需要读取的数据块block、访问令牌blockToken、客户端名称clientName、数据块读取的起始偏移量blockOffset、
// 数据读取的长度length、是否发送块校验sendChecksum、缓存策略CachingStrategy类型的