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