768 if (curVolume == startVolume) {
769 throw new DiskOutOfSpaceException("Insufficient space for an additional block");
770 }
771 }
[java]
828 synchronized List
829
830 ArrayList
831
832 for (int idx = 0; idx < volumes.length; idx++) {
833 FSVolume fsv = volumes[idx];
834 try {
835 fsv.checkDirs();
836 } catch (DiskErrorException e) {
837 DataNode.LOG.warn("Removing failed volume " + fsv + ": ",e);
838 if(removed_vols == null) {
839 removed_vols = new ArrayList
840 }
841 removed_vols.add(volumes[idx]);
842 volumes[idx].dfsUsage.shutdown(); //Shutdown the running DU thread
843 volumes[idx] = null; //remove the volume
844 }
845 }
846
847 // repair array - copy non null elements
848 int removed_size = (removed_vols==null) 0 : removed_vols.size();
849 if(removed_size > 0) {
850 FSVolume fsvs[] = new FSVolume [volumes.length-removed_size];
851 for(int idx=0,idy=0; idx
853 fsvs[idy] = volumes[idx];
854 idy++;
855 }
856 }
857 volumes = fsvs; // replace array of volumes
首先来看getNextVolume方法,该方法的主要作用是循环遍历DN的各个写入路径,通过volume.getAvailable方法获取一个能够写入给定block的路径。其中volume.getAvailable方法调用的就是上边提到的FSVolume的成员变量usage的getAvailable方法。
[java]
632 void checkDirs() throws DiskErrorException {
633 dataDir.checkDirTree();
634 DiskChecker.checkDir(tmpDir);
635 DiskChecker.checkDir(blocksBeingWritten);
636 }
可以看到调用了Fdir的checkDirTree,其实在这个方法中也是调用的DiskChecker.checkDir方法,只是FSDir管理每个路径的目录树。DiskChecker.checkDir方法主要做三个检查,检查路径是不是目录,是否可读,是否可写。
在看另外一个重要的方法,volumes.getVolumeMap(volumeMap);其实这个方法是对FSVolumeSet管理的所有FSVolume执行其中的getVolumeMap方法,而每个FSVolume对象执行的是管理其目录树的 dataDir.getVolumeMap。那我们最后来看FSDir的getVolumeMap方法,
[java]
318 if (children != null) {
319 for (int i = 0; i < children.length; i++) {
320 children[i].getVolumeMap(volumeMap, volume);
321 }
322 }
323
324 DataInputStream fileReader = null;
325 //对一个目录下的所有block文件进行遍历,可以在此处对localindex进行读取
326 File blockFiles[] = dir.listFiles();
327 if (blockFiles != null) {
328 for (int i = 0; i < blockFiles.length; i++) {
329 DataNode.LOG.info(" filename is : " + blockFiles[i].getName());
330 if (Block.isBlockFilename(blockFiles[i])) {
331 DataNode.LOG.info("in getVolumeMap: is blockFiles: " + blockFiles[i].getName());
332 long genStamp = FSDataset.getGenerationStampFromFile(blockFiles,
333 blockFiles[i]);
334 volumeMap.put(new Block(blockFiles[i], blockFiles[i].length(),
335 genStamp), new DatanodeBlockInfo(volume, blockFiles[i]));
336 } www.2cto.com
首先可以看到对每个子目录进行递归调用,然后针对文件目录中的每个文件进行遍历,最终建立一个 volumeMap, volumeMap是一个 HashMap
[java]
71
72 private long blockId;
73 private long numBytes;
74 private long generationStamp;
这些关于每个block的元