HDFS1.0源代码解析―DataNode端数据存储和管理DataStorage和FSDataset解析(二)

2014-11-24 08:47:01 · 作者: · 浏览: 3
xists();
470 boolean hasPreviousTmp = getPreviousTmp().exists();
471 boolean hasRemovedTmp = getRemovedTmp().exists();
472 boolean hasFinalizedTmp = getFinalizedTmp().exists();
473 boolean hasCheckpointTmp = getLastCheckpointTmp().exists();
之后判断个各种状态产什么的标志性文件是否存在,根据不同文件存在的情况返回不同的状态。
根据不同的返回状态,同样是该类中的doRecover方法进行处理,
[java]
534 public void doRecover(StorageState curState) throws IOException {
535 File curDir = getCurrentDir();
536 String rootPath = root.getCanonicalPath();
537 switch(curState) {
538 case COMPLETE_UPGRADE: // mv previous.tmp -> previous
539 LOG.info("Completing previous upgrade for storage directory "
540 + rootPath + ".");
541 rename(getPreviousTmp(), getPreviousDir());
542 return;
上边只是处理的一小部分代码,从这部分就可以看出该函数的主要功能就是根据目录当前所处的状态,将目录回复到某个稳定的状态。
至此我们介绍完了DataStorage在检查部分所做的工作,检查完之后,通过doTransition(getStorageDir(idx), nsInfo, startOpt); 进行一些必要的转换工作,主要根据current目录下的VERSION文件和startOpt选项决定(说实话这部分搞得不是很仔细,细节大家仔细研究吧)。最后通过 this.writeAll()将元信息写入。
通过上面的分析,我们基本就清楚了DataStorage的作用,检查配置的路径是否可用、是否处于一致的状态,根据这些状态进行处理和转换,尽量对目前的不一致状态进行恢复,所以DataStorage的作用相当于预处理。

下面开始介绍FSDataset的主要流程,还是先看FSDataset与DN的关系,在startDataNode方法中,
[java]
384 this.data = new FSDataset(storage, conf);
创建一个FSDataset的对象,接下来看一下创建对象的过程,借此了解FSDataset类的组成和功能。
[java] view plaincopyprint
1118 //获取配置的datanode的文件的路径
1119 String[] dataDirs = conf.getStrings(DataNode.DATA_DIR_KEY);
1120
1121 int volsConfigured=0;
1122
1123 if(dataDirs != null)
1124 volsConfigured = dataDirs.length;
1125
1126 //计算当前不能读取的datanode的目录的数目
1127 int volsFailed = volsConfigured - storage.getNumStorageDirs();


1143 //每个volum对应一个配置的路径
1144 FSVolume[] volArray = new FSVolume[storage.getNumStorageDirs()];
1145 for (int idx = 0; idx < storage.getNumStorageDirs(); idx++) {
1146 volArray[idx] = new FSVolume(storage.getStorageDir(idx).getCurrentDir(), conf);
1147 }
1148 //通过FSVolumSet管理各个volum
1149 volumes = new FSVolumeSet(volArray);
1150 //对每一个volum下的文件进行处理,加载volummap与sumindex volumes.getVolumeMap(volumeMap);
1151 volumes.getVolumeMap(volumeMap);
1152 File[] roots = new File[storage.getNumStorageDirs()];
1153 for (int idx = 0; idx < storage.getNumStorageDirs(); idx++) {
1154 roots[idx] = storage.getStorageDir(idx).getCurrentDir();
1155 }
1156 asyncDiskService = new FSDatasetAsyncDiskService(roots);
1157 registerMBean(storage.getStorageID());
首先读取配置的存储目录的数目,再与能够使用的存储目录数目做比较,看是否满足设定的需求。在往下我们可以看到每一个配置的目录使用一个FSVolume对象进行管理,下面我们看一个这个FSVolume对象初始化过程中具体做了哪些事情。FSVolume是 FSDataset的一个内部类。
[java]
463 class FSVolume {
464 private File currentDir;
465 private FSDir dataDir;
466 private File tmpDir;
467 private File blocksBeingWritten; // clients write here
468 private File detachDir; // copy on write for blocks in snapshot
469 private DF usage;
470 private DU dfsUsage;
471 private long reserved;
[java]
474 FSVolume(File currentDir, Configuration conf) throws IOException {
475 //每个磁盘写入点是否预留空间,决定dn是否将每个磁盘写入点写满
476 this.reserved = conf.getLong("dfs.datanode.du.reserved", 0);
477 this.dataDir = new FSDir(currentDir);
478 this.currentDir = currentDir;
479