public LocatedBlock addBlock(String src, String clientMachine) throws IOException {
int retries = 5;//设定重试次数为5
Object results[] = namesystem.getAdditionalBlock(new UTF8(src), new UTF8(clientMachine));
//获取新的一个Block和DataNode节点信息
while (results != null && results[0] == null && retries > 0) {
try {//发生错误,且不超过错误次数,就重新获取
Thread.sleep(100);
} catch (InterruptedException ie) {
}
results = namesystem.getAdditionalBlock(new UTF8(src), new UTF8(clientMachine));
retries--;
}
//无论如何,都结束了!
if (results == null) {//没找到?返回错误
throw new IOException("Cannot obtain additional block for file " + src);
} else if (results[0] == null) {
return null;//没有Block?返回null
} else {
Block b = (Block) results[0];
DatanodeInfo targets[] = (DatanodeInfo[]) results[1];
return new LocatedBlock(b, targets);//这个简单,返回Block和DatanodeInfo
}
}
=====================
C1:OKAY c2:OKAY c3:OKAY
=====================
下面开始讲解
public synchronized Object[] getAdditionalBlock(UTF8 src, UTF8 clientMachine) {
---
public synchronized Object[] getAdditionalBlock(UTF8 src, UTF8 clientMachine) {
Object results[] = null;
if (dir.getFile(src) == null && pendingCreates.get(src) != null) {
//文件系统dir中没有此文件且此文件正在创建过程中
results = new Object[2];//创建返回的变量数组
//
// If we fail this, bad things happen!
//这里的checkFileProgress很关键,
//后面会分析checkFileProgress的作用
if (checkFileProgress(src)) {
// Get the array of replication targets //这个仍然很简单,之前分析过了
DatanodeInfo targets[] = chooseTargets(this.desiredReplication, null, clientMachine);
if (targets.length < this.minReplication) {
return null;
}
// Create next block返回不多说!
results[0] = allocateBlock(src);
results[1] = targets;
}
}
return results;
}
===
接下来是函数
synchronized boolean checkFileProgress(UTF8 src) {
这个函数还是蛮重要的!
/**
* Check that the indicated file's blocks are present and
* replicated. If not, return false.
*/
synchronized boolean checkFileProgress(UTF8 src) {
Vector v = (Vector) pendingCreates.get(src);//获取文件名src对应的每个块
for (Iterator it = v.iterator(); it.hasNext(); ) {
Block b = (Block) it.next();//对于当前块来说
TreeSet containingNodes = (TreeSet) blocksMap.get(b);//获取这个块对应的datanode节点信息
if (containingNodes == null || containingNodes.size() < this.minReplication) {
return false;//如果此Block对应的datanode个数不足最小备份数,则禁止返回Block
}
}
return true;//顺利返回true.
}
从这个函数,我们得知,如果在写入的过程中有datanode挂机,但是受影响的block的总个数达到安全阀值,我们还是容许继续写入的!