namenode rpc server:
mkdirs:细化logEdit,核心类FSEditLog
- FSDirectory.getEditLog(),即FSEditLog-》logMkDir-》logEdit-》记录日志
- 满足可写入状态后,如果自动同步标识isAutoSyncScheduled为true,则阻塞;否则
- 自增txid,赋给线程本地变量,FSEditLogOp设置txid,editLogStream.wirite(op);
- JournalSetOutputStream.write-》遍历journals
- 先看下journals,包含JournalAndStream的list,在FSEditLog的journalSet初始化
- 遍历journal的QuorumOutputStream-》write-》双缓冲调用writeOp,最终MkdirOp序列化inodeid,path等信息到ByteArrayOutputStream;
- endTransaction
- 如果写磁盘,buffer满了,则isAutoSyncScheduled为true,让后续写磁盘阻塞;
- logSync-》交互缓冲区,logStream.flush();-》flushAndSync,一个刷新磁盘,另一个我们重点观看
- 创建buffer,把数据从备缓存提取出来,sendEdits,每个AsyncLogger代表一个jnode,遍历,调用sendEdits异步发送;
- 记录回调到map,把map添加到QuorumCall
- waitForWriteQuorum,阻塞等待结果,全部返回结束,一半加1成功返回,一半加1失败返回,否则多次等待,等待时间逐渐缩短,直到超时;
- 给每个AsyncLogger设置committedTxId
- 超时抛出超时异常,然后调用terminate结束当前进程(继续提供只读服务不也可以吗?并且这样会丢失一些元数据啊,怎么办?)
- 接下里看给jnode发送了什么内容?还有,失败的jnode要怎么处理?
- IPCLoggerChannel生成请求,journalId, epoch, ipcSerial++, committedTxId(已提交的txid)
- segmentTxId(FSEditLog的txid+1), firstTxnId(buffer的第一个txid), numTxns(buffer添加操作的计数), data
- 调用journal,看journalnode rpcserver如何处理
FSEditLog:
- private JournalSet journalSet初始化:管理JournalAndStream,JournalAndStream管理JournalManager和EditLogOutputStream
- FSNamesystem.startActiveServices-》initJournals-》读取core-site.xml hdfs-site.xml,解析uri scheme,初始化JournalManager,被添加到JournalAndStream
- 如果是file,初始化FileJournalManager(包含buffer容量),被添加到JournalAndStream;否则,该类有多个实现,通过配置文件指定uri scheme指定实现,目前添加的是QuorumJournalManager(包含buffer容量);
- 目前有两个JournalAndStream实例,一个是写磁盘一个是写jnode;
- private EditLogOutputStream editLogStream初始化:
- FSNamesystem.startActiveServices-》openForWrite-》startLogSegment-》new JournalSetOutputStream
EditLogOutputStream:
- EditLogOutputStream继承类有JournalSetOutputStream(editLogStream被初始化为该类,一个操作类),EditLogFileOutputStrem、QuorumOutputStream等;
- 上面后两个实现使用双缓存EditsDoubleBuffer,DataOutputBuffer继承自jdk.DataOutputStream,里面使用了ByteArrayOutputStream;
- 根据JournalAndStream中的,JournalManager的实现,初始化,FileJournalManager实现方法startLogSegment-》new EditLogFileOutputStream,QuorumJournalManager实现startLogSegment-》new QuorumOutputStream;
JournalNode:
- EditLogOutputStream curSegment = new EditLogFileOutputStream,成员变量初始化,该类主要作用写磁盘;
- 处理,namenode standby通过http发起的,获取日志的请求,/getJournal处理方法;
- journal
- 检查请求的epoch(和namenode启动有关),PersistentLongFile持久化long value,如果小于存储的,抛异常,否则,更新存储的epoch
- 判断segmentTxId是否相等,否则异常(收到rpc请求startLogSegment,初始化该值,在namenode启动时,QuorumJournalManager初始化stream时调用startLogSegment,发起rpc请求)
- 请求的ipcSerial是否更大,否则异常;更新值;
- 请求的committedTxId是否更大,否则异常,更新值;以上四步为检查请求;
- startLogSegment
- 检查请求-》如果存在segment,中断他
- FileJournalManager 获取请求txid的file,如果多个,异常;如果存在,可能断链重新链接,获取EditLogFile-》如果isInProgress false,异常;否则扫描文件,如果last和first txid不等,异常
- 如果请求的epoch不等,更新
- 删除segmentTxid对应的paxosfile
- 创建segment,初始化segmenttxid = txid,nextTxid = txid,每次joural请求也会更新nextTxid;
EditLogFile:
private File file;
private final long firstTxId;
private long lastTxId;
private boolean hasCorruptHeader = false;
private final boolean isInProgress;
java,面向对象思想,c 面向过程,c++基于两者之间;
如果看java开源和c++开源就是不一样的感觉;
java,拼命堆类,控制类的大小,各种跳转,各种设计模式;
c++,中性,对象和过程各一半;