github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/swarm/network/stream/intervals/intervals.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:43</date>
    10  //</624450115339292672>
    11  
    12  
    13  package intervals
    14  
    15  import (
    16  	"bytes"
    17  	"fmt"
    18  	"strconv"
    19  	"sync"
    20  )
    21  
    22  //间隔存储间隔列表。其目的是提供
    23  //方法添加新间隔并检索
    24  //需要添加。
    25  //它可以用于流数据的同步以保持
    26  //已检索到会话之间的数据范围。
    27  type Intervals struct {
    28  	start  uint64
    29  	ranges [][2]uint64
    30  	mu     sync.RWMutex
    31  }
    32  
    33  //新建创建间隔的新实例。
    34  //start参数限制间隔的下限。
    35  //添加方法或将不添加以下开始绑定的范围
    36  //由下一个方法返回。此限制可用于
    37  //跟踪“实时”同步,其中同步会话
    38  //从特定值开始,如果“实时”同步间隔
    39  //需要与历史相结合,才能安全地完成。
    40  func NewIntervals(start uint64) *Intervals {
    41  	return &Intervals{
    42  		start: start,
    43  	}
    44  }
    45  
    46  //添加将新范围添加到间隔。范围开始和结束都是值
    47  //都是包容性的。
    48  func (i *Intervals) Add(start, end uint64) {
    49  	i.mu.Lock()
    50  	defer i.mu.Unlock()
    51  
    52  	i.add(start, end)
    53  }
    54  
    55  func (i *Intervals) add(start, end uint64) {
    56  	if start < i.start {
    57  		start = i.start
    58  	}
    59  	if end < i.start {
    60  		return
    61  	}
    62  	minStartJ := -1
    63  	maxEndJ := -1
    64  	j := 0
    65  	for ; j < len(i.ranges); j++ {
    66  		if minStartJ < 0 {
    67  			if (start <= i.ranges[j][0] && end+1 >= i.ranges[j][0]) || (start <= i.ranges[j][1]+1 && end+1 >= i.ranges[j][1]) {
    68  				if i.ranges[j][0] < start {
    69  					start = i.ranges[j][0]
    70  				}
    71  				minStartJ = j
    72  			}
    73  		}
    74  		if (start <= i.ranges[j][1] && end+1 >= i.ranges[j][1]) || (start <= i.ranges[j][0] && end+1 >= i.ranges[j][0]) {
    75  			if i.ranges[j][1] > end {
    76  				end = i.ranges[j][1]
    77  			}
    78  			maxEndJ = j
    79  		}
    80  		if end+1 <= i.ranges[j][0] {
    81  			break
    82  		}
    83  	}
    84  	if minStartJ < 0 && maxEndJ < 0 {
    85  		i.ranges = append(i.ranges[:j], append([][2]uint64{{start, end}}, i.ranges[j:]...)...)
    86  		return
    87  	}
    88  	if minStartJ >= 0 {
    89  		i.ranges[minStartJ][0] = start
    90  	}
    91  	if maxEndJ >= 0 {
    92  		i.ranges[maxEndJ][1] = end
    93  	}
    94  	if minStartJ >= 0 && maxEndJ >= 0 && minStartJ != maxEndJ {
    95  		i.ranges[maxEndJ][0] = start
    96  		i.ranges = append(i.ranges[:minStartJ], i.ranges[maxEndJ:]...)
    97  	}
    98  }
    99  
   100  //合并将m间隔中的所有间隔添加到当前间隔。
   101  func (i *Intervals) Merge(m *Intervals) {
   102  	m.mu.RLock()
   103  	defer m.mu.RUnlock()
   104  	i.mu.Lock()
   105  	defer i.mu.Unlock()
   106  
   107  	for _, r := range m.ranges {
   108  		i.add(r[0], r[1])
   109  	}
   110  }
   111  
   112  //Next返回未完成的第一个范围间隔。返回
   113  //起始值和结束值都包含在内,这意味着整个范围
   114  //包括开始和结束需要增加,以填补差距
   115  //每隔一段时间。
   116  //如果下一个间隔在整数之后,则end的返回值为0
   117  //以间隔存储的范围。零结束值表示无限制
   118  //在下一个间隔长度。
   119  func (i *Intervals) Next() (start, end uint64) {
   120  	i.mu.RLock()
   121  	defer i.mu.RUnlock()
   122  
   123  	l := len(i.ranges)
   124  	if l == 0 {
   125  		return i.start, 0
   126  	}
   127  	if i.ranges[0][0] != i.start {
   128  		return i.start, i.ranges[0][0] - 1
   129  	}
   130  	if l == 1 {
   131  		return i.ranges[0][1] + 1, 0
   132  	}
   133  	return i.ranges[0][1] + 1, i.ranges[1][0] - 1
   134  }
   135  
   136  //Last返回最后一个间隔结束时的值。
   137  func (i *Intervals) Last() (end uint64) {
   138  	i.mu.RLock()
   139  	defer i.mu.RUnlock()
   140  
   141  	l := len(i.ranges)
   142  	if l == 0 {
   143  		return 0
   144  	}
   145  	return i.ranges[l-1][1]
   146  }
   147  
   148  //字符串返回范围间隔的描述性表示形式
   149  //以[]表示法,作为两个元素向量的列表。
   150  func (i *Intervals) String() string {
   151  	return fmt.Sprint(i.ranges)
   152  }
   153  
   154  //marshalbinary将间隔参数编码为分号分隔列表。
   155  //列表中的第一个元素是base36编码的起始值。以下
   156  //元素是由逗号分隔的两个base36编码值范围。
   157  func (i *Intervals) MarshalBinary() (data []byte, err error) {
   158  	d := make([][]byte, len(i.ranges)+1)
   159  	d[0] = []byte(strconv.FormatUint(i.start, 36))
   160  	for j := range i.ranges {
   161  		r := i.ranges[j]
   162  		d[j+1] = []byte(strconv.FormatUint(r[0], 36) + "," + strconv.FormatUint(r[1], 36))
   163  	}
   164  	return bytes.Join(d, []byte(";")), nil
   165  }
   166  
   167  //unmarshalbinary根据interval.marshalbinary格式解码数据。
   168  func (i *Intervals) UnmarshalBinary(data []byte) (err error) {
   169  	d := bytes.Split(data, []byte(";"))
   170  	l := len(d)
   171  	if l == 0 {
   172  		return nil
   173  	}
   174  	if l >= 1 {
   175  		i.start, err = strconv.ParseUint(string(d[0]), 36, 64)
   176  		if err != nil {
   177  			return err
   178  		}
   179  	}
   180  	if l == 1 {
   181  		return nil
   182  	}
   183  
   184  	i.ranges = make([][2]uint64, 0, l-1)
   185  	for j := 1; j < l; j++ {
   186  		r := bytes.SplitN(d[j], []byte(","), 2)
   187  		if len(r) < 2 {
   188  			return fmt.Errorf("range %d has less then 2 elements", j)
   189  		}
   190  		start, err := strconv.ParseUint(string(r[0]), 36, 64)
   191  		if err != nil {
   192  			return fmt.Errorf("parsing the first element in range %d: %v", j, err)
   193  		}
   194  		end, err := strconv.ParseUint(string(r[1]), 36, 64)
   195  		if err != nil {
   196  			return fmt.Errorf("parsing the second element in range %d: %v", j, err)
   197  		}
   198  		i.ranges = append(i.ranges, [2]uint64{start, end})
   199  	}
   200  
   201  	return nil
   202  }
   203