github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/swarm/storage/feed/lookup/lookup.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 19:16:44</date>
    10  //</624450119177080832>
    11  
    12  
    13  /*
    14  包查找定义源查找算法并提供用于放置更新的工具
    15  所以可以找到它们
    16  **/
    17  
    18  package lookup
    19  
    20  const maxuint64 = ^uint64(0)
    21  
    22  //LowestLevel将查找算法的频率分辨率设置为2的幂。
    23  const LowestLevel uint8 = 0 //默认值为0(1秒)
    24  
    25  //最高级别设置算法将以2的功率运行的最低频率。
    26  //25->2^25大约等于一年。
    27  const HighestLevel = 25 //默认值为25(~1年)
    28  
    29  //默认级别设置没有提示时将选择搜索的级别
    30  const DefaultLevel = HighestLevel
    31  
    32  //算法是查找算法的函数签名
    33  type Algorithm func(now uint64, hint Epoch, read ReadFunc) (value interface{}, err error)
    34  
    35  //查找查找具有小于或等于“now”的最高时间戳的更新
    36  //它接受了一个提示,应该是最后一次已知更新所在的时代。
    37  //如果您不知道最后一次更新发生在哪个时代,只需提交lookup.noclue
    38  //每次查找时都将调用read()。
    39  //仅当read()返回错误时才返回错误
    40  //如果未找到更新,则返回nil
    41  var Lookup Algorithm = FluzCapacitorAlgorithm
    42  
    43  //readfunc是lookup在每次试图查找值时调用的处理程序。
    44  //如果找不到值,它应该返回<nil>
    45  //如果找到一个值,它应该返回<nil>,但它的时间戳高于“now”
    46  //它只应在处理程序希望停止时返回错误。
    47  //完全查找过程。
    48  type ReadFunc func(epoch Epoch, now uint64) (interface{}, error)
    49  
    50  //noclue是一个提示,当查找调用程序没有
    51  //最后一次更新可能在哪里的线索
    52  var NoClue = Epoch{}
    53  
    54  //GetBaseTime返回给定
    55  //时间和水平
    56  func getBaseTime(t uint64, level uint8) uint64 {
    57  	return t & (maxuint64 << level)
    58  }
    59  
    60  //提示仅基于上一次已知更新时间创建提示
    61  func Hint(last uint64) Epoch {
    62  	return Epoch{
    63  		Time:  last,
    64  		Level: DefaultLevel,
    65  	}
    66  }
    67  
    68  //GetNextLevel返回下一次更新应处于的频率级别,前提是
    69  //上次更新是什么时间。
    70  //这是“last”和“now”的异或的第一个非零位,从最高有效位开始计数。
    71  //但仅限于不返回小于最后一个-1的级别
    72  func GetNextLevel(last Epoch, now uint64) uint8 {
    73  //第一个xor是当前时钟的最后一个epoch基时间。
    74  //这将把所有常见的最高有效位设置为零。
    75  	mix := (last.Base() ^ now)
    76  
    77  //然后,通过设置
    78  //这个水平是1。
    79  //如果下一个级别低于当前级别,则必须正好是级别1,而不是更低。
    80  	mix |= (1 << (last.Level - 1))
    81  
    82  //如果上一次更新在2^highest level秒之前,请选择最高级别
    83  	if mix > (maxuint64 >> (64 - HighestLevel - 1)) {
    84  		return HighestLevel
    85  	}
    86  
    87  //设置一个扫描非零位的掩码,从最高级别开始
    88  	mask := uint64(1 << (HighestLevel))
    89  
    90  	for i := uint8(HighestLevel); i > LowestLevel; i-- {
    91  if mix&mask != 0 { //如果我们找到一个非零位,这就是下一次更新应该达到的级别。
    92  			return i
    93  		}
    94  mask = mask >> 1 //把我们的钻头右移一个位置
    95  	}
    96  	return 0
    97  }
    98  
    99  //getnextepoch返回下一个更新应位于的epoch
   100  //根据上次更新的位置
   101  //现在几点了。
   102  func GetNextEpoch(last Epoch, now uint64) Epoch {
   103  	if last == NoClue {
   104  		return GetFirstEpoch(now)
   105  	}
   106  	level := GetNextLevel(last, now)
   107  	return Epoch{
   108  		Level: level,
   109  		Time:  now,
   110  	}
   111  }
   112  
   113  //GetFirstEpoch返回第一次更新应位于的epoch
   114  //根据现在的时间。
   115  func GetFirstEpoch(now uint64) Epoch {
   116  	return Epoch{Level: HighestLevel, Time: now}
   117  }
   118  
   119  var worstHint = Epoch{Time: 0, Level: 63}
   120  
   121  //FluzCapacitorAlgorithm的工作原理是,如果找到更新,则缩小epoch搜索区域。
   122  //及时往返
   123  //首先,如果提示是
   124  //最后一次更新。如果查找失败,则最后一次更新必须是提示本身
   125  //或者下面的时代。但是,如果查找成功,则更新必须是
   126  //或者在下面的时代里。
   127  //有关更图形化的表示,请参阅指南。
   128  func FluzCapacitorAlgorithm(now uint64, hint Epoch, read ReadFunc) (value interface{}, err error) {
   129  	var lastFound interface{}
   130  	var epoch Epoch
   131  	if hint == NoClue {
   132  		hint = worstHint
   133  	}
   134  
   135  	t := now
   136  
   137  	for {
   138  		epoch = GetNextEpoch(hint, t)
   139  		value, err = read(epoch, now)
   140  		if err != nil {
   141  			return nil, err
   142  		}
   143  		if value != nil {
   144  			lastFound = value
   145  			if epoch.Level == LowestLevel || epoch.Equals(hint) {
   146  				return value, nil
   147  			}
   148  			hint = epoch
   149  			continue
   150  		}
   151  		if epoch.Base() == hint.Base() {
   152  			if lastFound != nil {
   153  				return lastFound, nil
   154  			}
   155  //我们自己已经得到了暗示
   156  			if hint == worstHint {
   157  				return nil, nil
   158  			}
   159  //过来看
   160  			value, err = read(hint, now)
   161  			if err != nil {
   162  				return nil, err
   163  			}
   164  			if value != nil {
   165  				return value, nil
   166  			}
   167  //坏提示。
   168  			epoch = hint
   169  			hint = worstHint
   170  		}
   171  		base := epoch.Base()
   172  		if base == 0 {
   173  			return nil, nil
   174  		}
   175  		t = base - 1
   176  	}
   177  }
   178