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

  1. // 当前迭代级别
  2. private int level;
  3. // 标志位:是否为特定复制优先级的迭代器
  4. private boolean isIteratorForLevel = false;
  5. // 数据块Block迭代器Iterator列表,存储各级别数据块迭代器
  6. private final List<Iterator<Block>> iterators = new ArrayList<Iterator<Block>>();

其中,level代表了迭代器当前处于的迭代级别,表示正在哪个块复制级别迭代数据块;isIteratorForLevel是一个标志位,是否为特定复制优先级的迭代器的标志位,也就意味着只在特定级别进行迭代;而iterators则是一个数据块Block迭代器Iterator列表,由前往后、由高到低的存储各级别数据块迭代器。
        BlockIterator提供了两个构造函数,一个是无参构造函数:生成所有级别的数据块迭代器,另外一个是有参构造函数:生成指定级别的数据块迭代器,代码分别如下:

  1. /**
  2. * Construct an iterator over all queues.
  3. * 无参构造函数:生成所有级别的数据块迭代器
  4. */
  5. private BlockIterator() {
  6. // 当前迭代级别level设置为0
  7. level=0;
  8. // iterators中添加全部级别的数据块迭代器
  9. for(int i=0; i<LEVEL; i++) {
  10. iterators.add(priorityQueues.get(i).iterator());
  11. }
  12. }
  13. /**
  14. * Constrict an iterator for a single queue level
  15. * 有参构造函数:生成指定级别的数据块迭代器
  16. * @param l the priority level to iterate over
  17. */
  18. private BlockIterator(int l) {
  19. // 当前迭代级别level设置为指定级别
  20. level = l;
  21. // 标志位:是否为特定复制优先级的迭代器设置为true
  22. isIteratorForLevel = true;
  23. // iterators中添加指定级别的数据块迭代器
  24. iterators.add(priorityQueues.get(level).iterator());
  25. }

注释很清晰,读者可自行阅读。另外,数据块是根据复制级别由高到低的顺序迭代的,当某一级别数据块迭代完毕,那么我们需要更新当前迭代级别,此时update()方法就完成这一个工作,代码如下:

  1. // 如果需要,更新当前迭代级别(由高往低迭代)
  2. private void update() {
  3. // 标志位:是否为特定复制优先级的迭代器,为true的话,直接返回
  4. if (isIteratorForLevel) {
  5. return;
  6. }
  7. // 当前迭代级别小于LEVEL-1(也就是还没到最低级别),并且当前迭代级别已遍历所有数据块
  8. while(level< LEVEL-1 && !iterators.get(level).hasNext()) {
  9. // 当前迭代级别level加1
  10. level++;
  11. }
  12. }

它会先判断标志位isIteratorForLevel:是否为特定复制优先级的迭代器,为true的话,直接返回;否则当当前迭代级别小于LEVEL-1(也就是还没到最低级别),并且当前迭代级别已遍历所有数据块,当前迭代级别level加1。

既然是一个迭代器,那么我们看下它最重要的两个方法,hasNext()和next(),分别如下:

hasNext():判断是否还存在未迭代元素

  1. // 判断是否还有下一个元素
  2. @Override
  3. public boolean hasNext() {
  4. // 标志位:是否为特定复制优先级的迭代器,为true的话,直接返回iterators列表中第一个迭代器的判断下一个元素的结果
  5. if (isIteratorForLevel) {
  6. return iterators.get(0).hasNext();
  7. }
  8. // 如果需要,更新当前迭代级别(由高往低迭代)
  9. update();
  10. // 取当前级别的迭代器的判断是否存在下一个元素的结果
  11. return iterators.get(level).hasNext();
  12. }

hasNext()方法,也是先判断标志位isIteratorForLevel:是否为特定复制优先级的迭代器,为true的话,直接返回iterators列表中第一个迭代器的判断下一个元素的结果,否则,如果需要,调用update()方法更新当前迭代级别(由高往低迭代),取当前级别的迭代器的判断是否存在下一个元素的结果。

next()方法:跌倒下一个元素

  1. // 取下一个元素
  2. @Override
  3. public Block next() {
  4. // 标志位:是否为特定复制优先级的迭代器,为true的话,直接返回iterators列表中第一个迭代器的下一个元素
  5. if (isIteratorForLevel) {
  6. return iterators.get(0).next();
  7. }
  8. // 如果需要,更新当前迭代级别(由高往低迭代)
  9. update();
  10. // 取当前级别的迭代器的下一个元素
  11. return iterators.get(level).next();
  12. }

处理逻辑与hasNext()方法一致,不再赘述。

BlockIterator还提供了从迭代器中移除元素remove()方法及获取当前迭代级别的getPriority()方法,代码分别如下:

  1. // 移除
  2. @Override
  3. public void remove() {
  4. // 标志位:是否为特定复制优先级的迭代器,为true的话,直接返回iterators列表中第一个迭代器的移除结果
  5. if (isIteratorForLevel) {
  6. iterators.get(0).remove();
  7. } else {
  8. // 取当前级别的迭代器的移除的结果
  9. iterators.get(level).remove();
  10. }
  11. }
  12. // 获取当前迭代级别
  13. int getPriority() {
  14. return level;
  15. }

UnderReplicatedBlocks还提供了按照优先级由高到低的顺序,获取指定数目的待复制数据块的chooseUnderReplicatedBlocks()方法,代码如下:

  1. /**
  2. * Get a list of block lists to be replicated. The index of block lists
  3. * represents its replication priority. Replication index will be tracked for
  4. * each priority list separately in priorityToReplIdx map. Iterates through
  5. * all priority lists and find the elements after replication index. Once the
  6. * last priority lists reaches to end, all replication indexes will be set to
  7. * 0 and start from 1st priority list to fulfill the blockToProces count.
  8. *
  9. * @param blocksToProcess - number of blocks to fetch from underReplicated blocks.
  10. * @return Return a list of block lists to be replicated. The block list index
  11. *         represents its replication priority.
  12. */
  13. public synchronized List<List<Block>> chooseUnderReplicatedBlocks(
  14. int blocksToProcess) {
  15. // initialize data structure for the return value
  16. // 初始化做为返回值的数据结构,LEVEL大小的一个块列表的列表
  17. List<List<Block>> blocksToReplicate = new ArrayList<List<Block>>(LEVEL);
  18. // 每种优先级都添加一个空的数据块ArrayList列表
  19. for (int i = 0; i < LEVEL; i++) {
  20. blocksToReplicate.add(new ArrayList<Block>());
  21. }
  22. // 如果不存在需要复制的数据块,直接返回空的列表blocksToReplicate
  23. if (size() == 0) { // There are no blocks to collect.
  24. return blocksToReplicate;
  25. }
  26. int blockCount = 0;
  27. // 按照优先级从高到低处理
  28. for (int priority = 0; priority < LEVEL; priority++) {
  29. // Go through all blocks that need replications with current priority.
  30. // 构造指定级别priority的数据块迭代器BlockIterator实例neededReplicationsIterator
  31. BlockIterator neededReplicationsIterator = iterator(priority);
  32. // 根据指定级别priority从priorityToReplIdx中取之前已经处理到的位置索引replIndex
  33. Integer replIndex = priorityToReplIdx.get(priority);
  34. // skip to the first unprocessed block, which is at replIndex
  35. // 利用replIndex,数据块迭代器跳过之前已处理的数据块,指向下一个该处理的正确位置
  36. for (int i = 0; i < replIndex && neededReplicationsIterator.hasNext(); i++) {
  37. neededReplicationsIterator.next();
  38. }
  39. // blocksToProcess的值不能超过所有待复制数据块总数
  40. blocksToProcess = Math.min(blocksToProcess, size());
  41. // 如果已获取到足够的数据块,即blockCount等于blocksToProcess,直接跳出循环
  42. if (blockCount == blocksToProcess) {
  43. break;  // break if already expected blocks are obtained
  44. }
  45. // Loop through all remaining blocks in the list.
  46. // 通过迭代器neededReplicationsIterator迭代数据块,添加入返回集合blocksToReplicate中,
  47. // 并累加索引位置replIndex
  48. // 判断条件为当前已取数据块blockCount还未达到要求的blocksToProcess,
  49. // 同时数据块迭代器neededReplicationsIterator还有下一个元素
  50. while (blockCount < blocksToProcess
  51. && neededReplicationsIterator.hasNext()) {
  52. // 通过数据块迭代器neededReplicationsIterator取下一个数据块
  53. Block block = neededReplicationsIterator.next();
  54. // 将数据块添加到优先级priority对应的列表
  55. blocksToReplicate.get(priority).add(block);
  56. // 累加索引位置replIndex
  57. replIndex++;
  58. // 累加已获取数据块数目blockCount
  59. blockCount++;
  60. }
  61. // 如果迭代器中已没有元素,且已处理到最高级别,重置位置索引priorityToReplIdx为0,跳出循环
  62. if (!neededReplicationsIterator.hasNext()
  63. && neededReplicationsIterator.getPriority() == LEVEL - 1) {
  64. // reset all priorities replication index to 0 because there is no
  65. // recently added blocks in any list.
  66. for (int i = 0; i < LEVEL; i++) {
  67. priorityToReplIdx.put(i, 0);
  68. }
  69. break;
  70. }
  71. // 记录索引位置replIndex
  72. priorityToReplIdx.put(priority, replIndex);
  73. }
  74. // 返回获取到的数据块列表
  75. return blocksToReplicate;
  76. }

其处理逻辑大体如下:

1、初始化做为返回值的数据结构,LEVEL大小的一个块列表的列表blocksToReplicate;

2、每种优先级都添加一个空的数据块ArrayList列表;

3、如果不存在需要复制的数据块,直接返回空的列表blocksToReplicate;

4、按照优先级从高到低处理:

4.1、构造指定级别priority的数据块迭代器BlockIterator实例neededReplicationsIterator;

4.2、根据指定级别priority从priorityToReplIdx中取之前已经处理到的位置索引replIndex;

4.3、利用replIndex,数据块迭代器跳过之前已处理的数据块,指向下一个该处理的正确位置;

4.4、blocksToProcess的值不能超过所有待复制数据块总数;

4.5、如果已获取到足够的数据块,即blockCount等于blocksToProcess,直接跳出循环;

4.6、通过迭代器neededReplicationsIterator迭代数据块,添加入返回集合blocksToReplicate中,并累加索引位置replIndex,判断条件为当前已取数据块blockCount还未达到要求的blocksToProcess,同时数据块迭代器neededReplicationsIterator还有下一个元素:

4.6.1、通过数据块迭代器neededReplicationsIterator取下一个数据块;

4.6.2、将数据块添加到优先级priority对应的列表;

4.6.3、累加索引位置replIndex;

4.6.4、累加已获取数据块数目blockCount;

4.7、如果迭代器中已没有元素,且已处理到最高级别,重置位置索引priorityToReplIdx为0,跳出循环;

4.8、priorityToReplIdx中记录优先级priority对应索引位置replIndex;

5、返回获取到的数据块列表。

未完待续,敬请期待《HDFS源码分析之UnderReplicatedBlocks(二)》

HDFS源码分析之UnderReplicatedBlocks(二)的更多相关文章

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

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

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

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

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

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

  4. HDFS源码分析之数据块及副本状态BlockUCState、ReplicaState

    关于数据块.副本的介绍,请参考文章<HDFS源码分析之数据块Block.副本Replica>. 一.数据块状态BlockUCState 数据块状态用枚举类BlockUCState来表示,代 ...

  5. 手机自动化测试:appium源码分析之bootstrap二

    手机自动化测试:appium源码分析之bootstrap二   在bootstrap项目中的io.appium.android.bootstrap.handler包中的类都是对应的指令类, priva ...

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

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

  7. HDFS源码分析之LightWeightGSet

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

  8. HDFS源码分析数据块汇报之损坏数据块检测checkReplicaCorrupt()

    无论是第一次,还是之后的每次数据块汇报,名字名字节点都会对汇报上来的数据块进行检测,看看其是否为损坏的数据块.那么,损坏数据块是如何被检测的呢?本文,我们将研究下损坏数据块检测的checkReplic ...

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

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

随机推荐

  1. POJ3311 Hie with the Pie

    The Pizazz Pizzeria prides itself in delivering pizzas to its customers as fast as possible. Unfortu ...

  2. 洛谷 P1027 Car的旅行路线

    P1027 Car的旅行路线 题目描述 又到暑假了,住在城市A的Car想和朋友一起去城市B旅游.她知道每个城市都有四个飞机场,分别位于一个矩形的四个顶点上,同一个城市中两个机场之间有一条笔直的高速铁路 ...

  3. SQLite-FMDatabase用法

    FMDatabase用法 转载 http://blog.sina.com.cn/s/blog_94d94f1a01015gcr.html 以下是FMDB的一些基本使用,FMDB框架其实只是一层很薄的封 ...

  4. 移动WEB前端开发资源的一些素材

    meta篇: <meta name="viewport" content="width=device-width,initial-scale=1.0,user-sc ...

  5. node 监听接口

    var http = require('http'); var mysql = require('mysql'); var connection = mysql.createConnection({ ...

  6. StringTokenizer:字符串分隔用法简介

    StringTokenizer:字符串分隔解析类型 属于:java.util包. 1.构造函数. 1. StringTokenizer(String str) :构造一个用来解析str的StringT ...

  7. hdu 2145(迪杰斯特拉)

    zz's Mysterious Present Time Limit: 10000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java ...

  8. 【转载】Word2010编号列表&多级列表

    1.引用场景         对于一份标准.漂亮的word文档,编号列表和多级列表的设置时必不可少的,正因为有它们,文档看起来才更专业,使用起来才更加的方便.如下面截图一般,这是十分常见的多级列表设置 ...

  9. Guava源码学习(零)前言

    Guava是由Google出品的Java类库,功能强大且易用. 后续我会用多篇博客介绍Guava的使用方法,以及从源码层面分析其实现原理. 分析次序基于Guava的官方Wiki 基于版本:Guava ...

  10. TCPMon使用总结

    一.TCPMon介绍 TCPMon是apache下的一个项目,下载链接:http://ws.apache.org/commons/tcpmon/download.cgi TCPMon相当于一个中转站, ...