HDFS1.0源代码解析—DataNode启动(一)
来源:互联网 发布:装修预算软件 编辑:程序博客网 时间:2024/04/29 20:38
DataNode的启动实在DataNode.java中进行的,具体启动流程如下:
public static void main(String args[]) { secureMain(args, null); }
在secureMain中调用createDataNode方法,该方法
public static DataNode createDataNode(String args[], Configuration conf, SecureResources resources) throws IOException { DataNode dn = instantiateDataNode(args, conf, resources); runDatanodeDaemon(dn); return dn; }利用instantiateDataNode创建DataNode 对象,通过runDatanodeDaemon
dn.register(); dn.dataNodeThread = new Thread(dn, dnThreadName); dn.dataNodeThread.setDaemon(true); // needed for JUnit testing dn.dataNodeThread.start();
进行DataNode注册,创建线程,设置守护线程,启动线程。
以上就是DataNode主线程启动的过程。
其中,创建创建DataNode 对象的过程如下:
在函数instantiateDataNode中, 调用makeInstance函数
//获取配置文件中的dfs.data.dir配置的文件路径 String[] dataDirs = conf.getStrings(DATA_DIR_KEY); makeInstance(dataDirs, conf, resources);在makeInstance函数中,创建dfs.data.dir指定的文件路径,确保至少有一个路径可以被创建,然后调用 DataNode的构造函数。具体如下:
for (String dir : dataDirs) { try { //进行用户权限的查询 DiskChecker.checkDir(localFS, new Path(dir), dataDirPermission); //dir存储检查之后的存储文件目录 dirs.add(new File(dir)); } catch(IOException e) { LOG.warn("Invalid directory in " + DATA_DIR_KEY + ": " + e.getMessage()); } } if (dirs.size() > 0)//至少有一个路径是可创建的 return new DataNode(conf, dirs, resources);DataNode构造函数中调用 startDataNode根据具体配置文件的信息进行具体的初始化过程。 startDataNode具体执行流程如下:
InetSocketAddress nameNodeAddr = NameNode.getServiceAddress(conf, true);
获取配置文件中fs.default.name指定的IP和端口。
// connect to name node this.namenode = (DatanodeProtocol) RPC.waitForProxy(DatanodeProtocol.class, DatanodeProtocol.versionID, nameNodeAddr, conf);//通过Hadoop的RPC机制与NameNode进行连接,获取namenode变量,这是DataNode与NameNode进行交互的工具 // get version and id info from the name-node NamespaceInfo nsInfo = handshake(); StartupOption startOpt = getStartupOption(conf);//获取DataNode启动的模式是regular还是format,如果是第一次启动必须指定format,不指定默认是regular
static public enum StartupOption{ FORMAT ("-format"), REGULAR ("-regular"), UPGRADE ("-upgrade"), ROLLBACK("-rollback"), FINALIZE("-finalize"), IMPORT ("-importCheckpoint");
这些是DataNode可能处于的一些状态。具体状态的切换见另外一篇日志的分析http://blog.csdn.net/zhangchunminggucas/article/details/7556050。
boolean simulatedFSDataset = conf.getBoolean("dfs.datanode.simulateddatastorage", false); if (simulatedFSDataset) {
这段代码判断是否是伪分布模式。之后会根据data中存储的文件和数据的特点判断是否需要进行恢复、升级、回滚的操作,如果没有按正常流程启动。
storage.recoverTransitionRead(nsInfo, dataDirs, startOpt);调用DataStorage类中的recoverTransitionRead进行检查,具体代码如下:
for(Iterator<File> it = dataDirs.iterator(); it.hasNext();) { File dataDir = it.next(); StorageDirectory sd = new StorageDirectory(dataDir);//初始化storage中的root StorageState curState; try { curState = sd.analyzeStorage(startOpt); // sd is locked but not opened switch(curState) { case NORMAL: break; case NON_EXISTENT: // ignore this storage LOG.info("Storage directory " + dataDir + " does not exist."); it.remove(); continue; case NOT_FORMATTED: // format LOG.info("Storage directory " + dataDir + " is not formatted."); LOG.info("Formatting ..."); format(sd, nsInfo); break; default: // recovery part is common sd.doRecover(curState); } } catch (IOException ioe) { sd.unlock(); throw ioe; } // add to the storage list addStorageDir(sd); dataDirStates.add(curState);
具体执行是在Storage.java中的analyzeStorage,通过检查返回当前所处的状态,在switch分支中不能处理的分支交与doRecover方法实现。处理完之后会根据StartupOption进行响应的处理,具体由 doTransition(getStorageDir(idx), nsInfo, startOpt);方法执行,该方法的详细解释在另外一篇博客http://blog.csdn.net/zhangchunminggucas/article/details/7556050,最后执行this.writeAll(); 将元信息写入磁盘。
当前DataNode可能处于一下状态:
public enum StorageState { NON_EXISTENT,//数据不存在,不做处理 NOT_FORMATTED,//没有进行初始化 COMPLETE_UPGRADE,//完成升级 RECOVER_UPGRADE,//取消升级 COMPLETE_FINALIZE,//完成提交 COMPLETE_ROLLBACK,//取消提交 RECOVER_ROLLBACK,//取消回滚 COMPLETE_CHECKPOINT,//NameNode用到,完成checkpoint的恢复 RECOVER_CHECKPOINT,//取消checkpoint恢复 NORMAL;//正常启动 }analyzeStorage函数是Storage.java中比较重要的一个函数,主要的实现流程是:首先,根据数据目录是否存在和StartupOption选项判断状态是数据不存在还是没有进行初始化。然后根据下面的状态判断DataNode处于的状态,将获得的状态信息返回给recoverTransitionRead进行处理。
// check whether current directory is valid File versionFile = getVersionFile();//获取current下的VERSION文件 boolean hasCurrent = versionFile.exists(); // check which directories exist boolean hasPrevious = getPreviousDir().exists(); boolean hasPreviousTmp = getPreviousTmp().exists(); boolean hasRemovedTmp = getRemovedTmp().exists(); boolean hasFinalizedTmp = getFinalizedTmp().exists(); boolean hasCheckpointTmp = getLastCheckpointTmp().exists();
storage.recoverTransitionRead函数分析完之后,我们继续分析下一个函数 this.data = new FSDataset(storage, conf);在FSDataset构造函数中,主要完成对current目录下文件的遍历,建立volumes、volumeMap、roots。其中volumes是FSVolumeSet对象,用于管理各个FSVolume,每一个data的存储目录(即dfs.data.dirFSVolume指定的每个文件路径)对应一个FSVolume对象,FSVolume对象会记录对应路径的磁盘使用情况,以及 dataDir ,其中this.dataDir = new FSDir(currentDir);管理FSVolume对象对应磁盘路径的目录结构。volumeMap是HashMap<Block,DatanodeBlockInfo>类型的对象,建立的是Block和DatanodeBlockInfo之间的对应关系,其中Block记录blockid、block大小、generationStamp,DatanodeBlockInfo记录对应的FSVolume,block的file对象。
- HDFS1.0源代码解析—DataNode启动(一)
- HDFS1.0源代码解析—DataNode启动(二)
- HDFS1.0源代码解析—DataNode启动(三)
- HDFS1.0源代码解析—DataNode状态切换
- HDFS1.0源代码解析—DataNode端数据存储和管理DataStorage和FSDataset解析
- HDFS1.0源代码解析—DataNode数据接收线程DataXceiverServer与DataXceiver解析
- HDFS1.0源代码解析—DataNode类主要数据成员和函数
- HDFS1.0源代码解析—Hadoop的RPC机制之Client解析
- HDFS1.0源代码解析—Hadoop的RPC机制之Server端解析
- HDFS1.0源代码解析—数据传输和接受的类BlockSender和BlockReceiver
- Hadoop DataNode启动之DiskChecker(一)
- hadoop block源代码分析DataNode部分(一)
- Hadoop DataNode启动之创建NameNode代理(一)
- Torque源代码解析(一)
- emule源代码解析(一)
- tinyxml源代码解析(一)
- hdfs集群启动——datanode注册(2)
- Ogre源代码浅析——脚本及其解析(一)
- Android开发网上的一些重要知识点
- asp.net页面指定控件导出为Word 或excel 文档
- label bias problem
- poj 1474 半平面交求多边形的核
- CATransform3D-Cube
- HDFS1.0源代码解析—DataNode启动(一)
- 用usb安装ubuntu server 10.04(好像所有操作系统都能通过此方法安装)
- poj1523[割顶&连通分支数]
- 查看mysql表结构和表创建语句的方法
- 关于委托的简单认识
- Android 移植到C#
- 判断字节序的一个方法
- vi查找替换命令详解
- (精)河南省第4届acm(表达式求值)