EditsDoubleBuffer是为edits准备的双缓冲区。新的编辑被写入第一个缓冲区,同时第二个缓冲区可以被flush。为edits准备的双缓冲区。新的编辑被写入第一个缓冲区,同时第二个缓冲区可以被flush。在其内部,有两个重要的缓冲区成员变量,如下:

  1. // 当前被写入的缓冲区bufCurrent
  2. private TxnBuffer bufCurrent; // current buffer for writing
  3. // 正在进行flush的缓冲区bufReady
  4. private TxnBuffer bufReady; // buffer ready for flushing
  5. // 初始化缓冲区大小initBufferSize
  6. private final int initBufferSize;

其中,bufCurrent是当前被写入的缓冲区,当前被写入的缓冲区是正在进行flush的缓冲区,而initBufferSize则是初始化缓冲区大小。我们再看下EditsDoubleBuffer的构造函数,如下:

  1. // 构造函数
  2. public EditsDoubleBuffer(int defaultBufferSize) {
  3. // 根据入参赋值initBufferSizeinitBufferSize
  4. initBufferSize = defaultBufferSize;
  5. // 创建当前被写入的缓冲区bufCurrent
  6. bufCurrent = new TxnBuffer(initBufferSize);
  7. // 创建正在进行flush的缓冲区bufReady
  8. bufReady = new TxnBuffer(initBufferSize);
  9. }

根据入参赋值initBufferSizeinitBufferSize,然后分别创建上述两个缓冲区:创建当前被写入的缓冲区bufCurrent、创建正在进行flush的缓冲区bufReady。

而EditsDoubleBuffer最基本的写入功能有两个,一个是用于写入操作符的writeOp()方法,另外一个就是用于写入事务的writeRaw()方法,代码分别如下:

  1. // 写入操作符至bufCurrent
  2. public void writeOp(FSEditLogOp op) throws IOException {
  3. bufCurrent.writeOp(op);
  4. }
  5. // 写入事务至bufCurrent
  6. public void writeRaw(byte[] bytes, int offset, int length) throws IOException {
  7. bufCurrent.write(bytes, offset, length);
  8. }

均是将操作符或事物写入bufCurrent缓冲区。而在准备flush前,需要先调用setReadyToFlush()方法,设置缓冲区可以进行flush,代码如下:

  1. // 设置双缓冲区为可以进行flsuh
  2. public void setReadyToFlush() {
  3. // 确保之前的数据已经被flush完毕,调用isFlushed()方法判断bufReady的大小是否为0即可
  4. assert isFlushed() : "previous data not flushed yet";
  5. // 交换bufReady、bufCurrent
  6. TxnBuffer tmp = bufReady;
  7. bufReady = bufCurrent;
  8. bufCurrent = tmp;
  9. }

它首先会确保之前的数据已经被flush完毕,调用isFlushed()方法判断bufReady的大小是否为0即可,然后交换bufReady、bufCurrent。

接着,我们需要调用flushTo()方法,将bufReady的内容写入指定输出流,并清空bufReady。此时不交换任何缓冲区,代码如下:

  1. /**
  2. * Writes the content of the "ready" buffer to the given output stream,
  3. * and resets it. Does not swap any buffers.
  4. * 将bufReady的内容写入指定输出流,并清空bufReady。此时不交换任何缓冲区。
  5. */
  6. public void flushTo(OutputStream out) throws IOException {
  7. bufReady.writeTo(out); // write data to file
  8. bufReady.reset(); // erase all data in the buffer
  9. }

而bufCurrent、bufReady都是一个TxnBuffer类型的缓冲区,这个TxnBuffer是对DataOutputBuffer的一个封装,保存了第一个事务艾迪firstTxId、事务数量numTxns、写入者writer等变量,它主要的两个方法,一个是写入操作符的writeOp()方法,实现如下:

  1. // 写入操作符
  2. public void writeOp(FSEditLogOp op) throws IOException {
  3. // 首次事务艾迪firstTxId被赋值为操作符的事务ID
  4. if (firstTxId == HdfsConstants.INVALID_TXID) {
  5. firstTxId = op.txid;
  6. } else {
  7. // 之后确保操作符的事务ID永远大于首次事务ID
  8. assert op.txid > firstTxId;
  9. }
  10. // 调用writer写入操作符
  11. writer.writeOp(op);
  12. // 事务数量numTxns累加
  13. numTxns++;
  14. }

首次事务艾迪firstTxId被赋值为操作符的事务ID,之后确保操作符的事务ID永远大于首次事务ID,然后调用writer写入操作符,并将事务数量numTxns累加。

HDFS源码分析之编辑日志编辑相关双缓冲区EditsDoubleBuffer的更多相关文章

  1. HDFS源码分析EditLog之获取编辑日志输入流

    在<HDFS源码分析之EditLogTailer>一文中,我们详细了解了编辑日志跟踪器EditLogTailer的实现,介绍了其内部编辑日志追踪线程EditLogTailerThread的 ...

  2. HDFS源码分析EditLog之读取操作符

    在<HDFS源码分析EditLog之获取编辑日志输入流>一文中,我们详细了解了如何获取编辑日志输入流EditLogInputStream.在我们得到编辑日志输入流后,是不是就该从输入流中获 ...

  3. HDFS源码分析数据块校验之DataBlockScanner

    DataBlockScanner是运行在数据节点DataNode上的一个后台线程.它为所有的块池管理块扫描.针对每个块池,一个BlockPoolSliceScanner对象将会被创建,其运行在一个单独 ...

  4. HDFS源码分析心跳汇报之数据块汇报

    在<HDFS源码分析心跳汇报之数据块增量汇报>一文中,我们详细介绍了数据块增量汇报的内容,了解到它是时间间隔更长的正常数据块汇报周期内一个smaller的数据块汇报,它负责将DataNod ...

  5. HDFS源码分析心跳汇报之BPServiceActor工作线程运行流程

    在<HDFS源码分析心跳汇报之数据结构初始化>一文中,我们了解到HDFS心跳相关的BlockPoolManager.BPOfferService.BPServiceActor三者之间的关系 ...

  6. HDFS源码分析之UnderReplicatedBlocks(一)

    http://blog.csdn.net/lipeng_bigdata/article/details/51160359 UnderReplicatedBlocks是HDFS中关于块复制的一个重要数据 ...

  7. HDFS源码分析数据块复制监控线程ReplicationMonitor(二)

    HDFS源码分析数据块复制监控线程ReplicationMonitor(二)

  8. HDFS源码分析数据块复制监控线程ReplicationMonitor(一)

    ReplicationMonitor是HDFS中关于数据块复制的监控线程,它的主要作用就是计算DataNode工作,并将复制请求超时的块重新加入到待调度队列.其定义及作为线程核心的run()方法如下: ...

  9. HDFS源码分析之UnderReplicatedBlocks(二)

    UnderReplicatedBlocks还提供了一个数据块迭代器BlockIterator,用于遍历其中的数据块.它是UnderReplicatedBlocks的内部类,有三个成员变量,如下: // ...

  10. HDFS源码分析之LightWeightGSet

    LightWeightGSet是名字节点NameNode在内存中存储全部数据块信息的类BlocksMap需要的一个重要数据结构,它是一个占用较低内存的集合的实现,它使用一个数组array存储元素,使用 ...

随机推荐

  1. 【HDOJ5972】Regular Number(Bitset,ShiftAnd)

    题意:给你N位数,接下来有N行,第i行先输入n,表示这个数的第i 位上可以在接下来的n个数中挑选,然后i 行再输n个数. 然后输入需要匹配的母串,让你输出母串中有多少个可行的N位子串. n<=1 ...

  2. VS2008 没办法太强大了

    原文发布时间为:2009-06-13 -- 来源于本人的百度文章 [由搬家工具导入] VS2008 太强大了。。。继续学习。。。。现在微软的某些强大功能也是针对 VS2008了。。。所以。。必须得装上 ...

  3. 配置微信api调扫码功能

    var url = encodeURIComponent(location.href.split('#')[0]); $.get(iapi+'/htweb/wx/getJsSdkSign?url='+ ...

  4. linux多线程学习笔记五--线程安全【转】

    转自:http://blog.csdn.net/kkxgx/article/details/7506085 版权声明:本文为博主原创文章,未经博主允许不得转载. 一,线程安全基础 一个函数被称为线程安 ...

  5. springBoot 编写接口

    @Slf4j @RestController public class testController { @Autowired StringRedisTemplate redis; @RequestM ...

  6. Android Studio中删除所有的断点

    直接上图,我相信你们能看的懂,骚年们. 第1个图:Run–>>View Breakpoints.. 第2个图:现在可以看到所有的断点了,在左侧栏全选,然后点"-",就全 ...

  7. RecyclerView的Item和Item内的控件点击处理

    需求场景:RecyclerView的Item需要点击,或者Item中的某个控件需要点击,或者两者同时需要点击处理. 一.adapter代码如下: package com.ldw.adapter; im ...

  8. Codeforces Gym100814 I.Salem-异或 (ACM International Collegiate Programming Contest, Egyptian Collegiate Programming Contest (2015) Arab Academy for Science and Technology)

    这个题就是二进制,找两个数相应的二进制相对应的位置上数不同的最多的个数.异或写就可以. 一开始还想麻烦了,找出来最大的偶数和最大的奇数,最小的偶数和最小的奇数,但是这样想考虑的不全.因为范围比较小,直 ...

  9. rownum详解

    对于rownum来说它是oracle系统顺序分配为从查询返回的行的编号,返回的第一行分配的是1,第二行是2,依此类推,这个伪字段可以用于限制查询返回的总行数,且rownum不能以任何表的名称作为前缀. ...

  10. HDU 3150 Robot Roll Call – Cambot…Servo…Gypsy…Croooow(map)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3150 Problem Description Mystery Science Theater 3000 ...