DataNode本地数据存储和管理(五)
的前面都不会发生改变,会变的也就只有新块中的最后一个校验和字段,可能这个校验和字段变短了)
[java]
private synchronized List tryUpdateBlock(
Block oldblock, Block newblock) throws IOException {
//check ongoing create threads
final ActiveFile activefile = ongoingCreates.get(oldblock);//获取与此块相关的文件及访问这个块的线程
if (activefile != null && !activefile.threads.isEmpty()) {//如果近期有对此块进行操作,返回存活的操作线程
//remove dead threads
for(Iterator i = activefile.threads.iterator(); i.hasNext(); ) {
final Thread t = i.next();
if (!t.isAlive()) {
i.remove();
}
}
//return living threads
//近期有对旧块进行操作,将存活的线程返回
if (!activefile.threads.isEmpty()) {
return new ArrayList(activefile.threads);
}
}
//近期无对此块操作的线程,就更新块
//No ongoing create threads is alive. Update block.
File blockFile = findBlockFile(oldblock.getBlockId());//获得旧块的文件
if (blockFile == null) {
throw new IOException("Block " + oldblock + " does not exist.");
}
//获得旧块的元数据文件
File oldMetaFile = findMetaFile(blockFile);
//获得旧块中的genStamp
long oldgs = parseGenerationStamp(blockFile, oldMetaFile);
//rename meta file to a tmp file
//先将旧块元数据文件重命名
File tmpMetaFile = new File(oldMetaFile.getParent(),
oldMetaFile.getName()+"_tmp" + newblock.getGenerationStamp());
if (!oldMetaFile.renameTo(tmpMetaFile)){
throw new IOException("Cannot rename block meta file to " + tmpMetaFile);
}
//旧块stamp比新块stamp大,不合法
if (oldgs > newblock.getGenerationStamp()) {
throw new IOException("Cannot update block (id=" + newblock.getBlockId()
+ ") generation stamp from " + oldgs
+ " to " + newblock.getGenerationStamp());
}
//update length
//新块的大小大于旧块的大小
if (newblock.getNumBytes() > oldblock.getNumBytes()) {
throw new IOException("Cannot update block file (=" + blockFile
+ ") length from " + oldblock.getNumBytes() + " to " + newblock.getNumBytes());
}
//新块的大小小于旧块的大小
if (newblock.getNumBytes() < oldblock.getNumBytes()) {
//截断旧块和旧块的元数据文件
truncateBlock(blockFile, tmpMetaFile, oldblock.getNumBytes(), newblock.getNumBytes());
}
//rename the tmp file to the new meta file (with new generation stamp)
//将重命名后的旧元数据文件重命名为新块元数据文件
File newMetaFile = getMetaFile(blockFile, newblock);
if (!tmpMetaFile.renameTo(newMetaFile)) {
throw new IOException("Cannot rename tmp meta file to " + newMetaFile);
}
updateBlockMap(ongoingCreates, oldblock, newblock);
updateBlockMap(volumeMap, oldblock, newblock);
// verify that the contents of the stored block
// matches the block file on disk.
validateBlockMetadata(newblock);
return null;
}
//truncateBlock对旧块blockFile和对应的元数据文件metaFile进行截断,截断后旧块长度为newlen(newlen
static private void truncateBlock(File blockFile, File metaFile,
long oldlen, long newlen) throws IOException {
if (newlen == oldlen) {
return;
}
if (newlen > oldlen) {
throw new IOException("Cannout truncate block to from oldlen (=" + oldlen
+ ") to newlen (=" + newlen + ")");
}
//由于只是对就块进行截断,所有新块的最后一个校验和字段可能在旧块中不一样,
//所有setLength进行截断后,要读取最后一个校验和字段
DataChecksum dcs = BlockMetadataHeader.readHeader(metaFile).getChecksum();
int checks