FsDatasetSpi接口里定义adjustCrcChannelPosition方法。
应用场景在:append,block recovery等场景。
方法的作用是设置checksum 流(datanode上meta文件)的文件指针,来让最后一个checksum被覆写。
/**
* Sets the file pointer of the checksum stream so that the last checksum
* will be overwritten
* @param b block
* @param outs The streams for the data file and checksum file
* @param checksumSize number of bytes each checksum has
* @throws IOException
*/
void adjustCrcChannelPosition(ExtendedBlock b,
ReplicaOutputStreams outs, int checksumSize) throws IOException;
三个参数也比较好理解:
- b :某个块。
- outs : 包含块的副本和meta文件的输出流。
- checksumSize: 每个checksum的字节数。
看下具体实现:
org.apache.hadoop.hdfs.server.datanode.fsdataset.impl.FsDatasetImpl#adjustCrcChannelPosition
设置meta文件的offset。逻辑比较简单:
就是拿到checksum的输出流,然后获取到FileChannel对象。
接着调用channel.position()
获取到当前所在的position,然后减去一个checksum的字节数得到新的position。
接着调用channel.position(newPos)
把新position设置上去。这样就会覆写最后一个checksum了。
/**
* Sets the offset in the meta file so that the
* last checksum will be overwritten.
*/
@Override // FsDatasetSpi
public void adjustCrcChannelPosition(ExtendedBlock b, ReplicaOutputStreams streams,
int checksumSize) throws IOException {
FileOutputStream file = (FileOutputStream)streams.getChecksumOut();
FileChannel channel = file.getChannel();
long oldPos = channel.position();
long newPos = oldPos - checksumSize;
if (LOG.isDebugEnabled()) {
LOG.debug("Changing meta file offset of block " + b + " from " +
oldPos + " to " + newPos);
}
channel.position(newPos);
}