github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/swarm/network/stream/intervals/intervals.go (about)

     1  
     2  //此源码被清华学神尹成大魔王专业翻译分析并修改
     3  //尹成QQ77025077
     4  //尹成微信18510341407
     5  //尹成所在QQ群721929980
     6  //尹成邮箱 yinc13@mails.tsinghua.edu.cn
     7  //尹成毕业于清华大学,微软区块链领域全球最有价值专家
     8  //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620
     9  //
    10  //
    11  //
    12  //
    13  //
    14  //
    15  //
    16  //
    17  //
    18  //
    19  //
    20  //
    21  //
    22  //
    23  //
    24  
    25  package intervals
    26  
    27  import (
    28  	"bytes"
    29  	"fmt"
    30  	"strconv"
    31  	"sync"
    32  )
    33  
    34  //
    35  //
    36  //
    37  //
    38  //
    39  type Intervals struct {
    40  	start  uint64
    41  	ranges [][2]uint64
    42  	mu     sync.RWMutex
    43  }
    44  
    45  //
    46  //
    47  //
    48  //
    49  //
    50  //
    51  //
    52  func NewIntervals(start uint64) *Intervals {
    53  	return &Intervals{
    54  		start: start,
    55  	}
    56  }
    57  
    58  //
    59  //
    60  func (i *Intervals) Add(start, end uint64) {
    61  	i.mu.Lock()
    62  	defer i.mu.Unlock()
    63  
    64  	i.add(start, end)
    65  }
    66  
    67  func (i *Intervals) add(start, end uint64) {
    68  	if start < i.start {
    69  		start = i.start
    70  	}
    71  	if end < i.start {
    72  		return
    73  	}
    74  	minStartJ := -1
    75  	maxEndJ := -1
    76  	j := 0
    77  	for ; j < len(i.ranges); j++ {
    78  		if minStartJ < 0 {
    79  			if (start <= i.ranges[j][0] && end+1 >= i.ranges[j][0]) || (start <= i.ranges[j][1]+1 && end+1 >= i.ranges[j][1]) {
    80  				if i.ranges[j][0] < start {
    81  					start = i.ranges[j][0]
    82  				}
    83  				minStartJ = j
    84  			}
    85  		}
    86  		if (start <= i.ranges[j][1] && end+1 >= i.ranges[j][1]) || (start <= i.ranges[j][0] && end+1 >= i.ranges[j][0]) {
    87  			if i.ranges[j][1] > end {
    88  				end = i.ranges[j][1]
    89  			}
    90  			maxEndJ = j
    91  		}
    92  		if end+1 <= i.ranges[j][0] {
    93  			break
    94  		}
    95  	}
    96  	if minStartJ < 0 && maxEndJ < 0 {
    97  		i.ranges = append(i.ranges[:j], append([][2]uint64{{start, end}}, i.ranges[j:]...)...)
    98  		return
    99  	}
   100  	if minStartJ >= 0 {
   101  		i.ranges[minStartJ][0] = start
   102  	}
   103  	if maxEndJ >= 0 {
   104  		i.ranges[maxEndJ][1] = end
   105  	}
   106  	if minStartJ >= 0 && maxEndJ >= 0 && minStartJ != maxEndJ {
   107  		i.ranges[maxEndJ][0] = start
   108  		i.ranges = append(i.ranges[:minStartJ], i.ranges[maxEndJ:]...)
   109  	}
   110  }
   111  
   112  //
   113  func (i *Intervals) Merge(m *Intervals) {
   114  	m.mu.RLock()
   115  	defer m.mu.RUnlock()
   116  	i.mu.Lock()
   117  	defer i.mu.Unlock()
   118  
   119  	for _, r := range m.ranges {
   120  		i.add(r[0], r[1])
   121  	}
   122  }
   123  
   124  //
   125  //
   126  //
   127  //
   128  //
   129  //
   130  //
   131  func (i *Intervals) Next() (start, end uint64) {
   132  	i.mu.RLock()
   133  	defer i.mu.RUnlock()
   134  
   135  	l := len(i.ranges)
   136  	if l == 0 {
   137  		return i.start, 0
   138  	}
   139  	if i.ranges[0][0] != i.start {
   140  		return i.start, i.ranges[0][0] - 1
   141  	}
   142  	if l == 1 {
   143  		return i.ranges[0][1] + 1, 0
   144  	}
   145  	return i.ranges[0][1] + 1, i.ranges[1][0] - 1
   146  }
   147  
   148  //
   149  func (i *Intervals) Last() (end uint64) {
   150  	i.mu.RLock()
   151  	defer i.mu.RUnlock()
   152  
   153  	l := len(i.ranges)
   154  	if l == 0 {
   155  		return 0
   156  	}
   157  	return i.ranges[l-1][1]
   158  }
   159  
   160  //
   161  //
   162  func (i *Intervals) String() string {
   163  	return fmt.Sprint(i.ranges)
   164  }
   165  
   166  //
   167  //
   168  //
   169  func (i *Intervals) MarshalBinary() (data []byte, err error) {
   170  	d := make([][]byte, len(i.ranges)+1)
   171  	d[0] = []byte(strconv.FormatUint(i.start, 36))
   172  	for j := range i.ranges {
   173  		r := i.ranges[j]
   174  		d[j+1] = []byte(strconv.FormatUint(r[0], 36) + "," + strconv.FormatUint(r[1], 36))
   175  	}
   176  	return bytes.Join(d, []byte(";")), nil
   177  }
   178  
   179  //
   180  func (i *Intervals) UnmarshalBinary(data []byte) (err error) {
   181  	d := bytes.Split(data, []byte(";"))
   182  	l := len(d)
   183  	if l == 0 {
   184  		return nil
   185  	}
   186  	if l >= 1 {
   187  		i.start, err = strconv.ParseUint(string(d[0]), 36, 64)
   188  		if err != nil {
   189  			return err
   190  		}
   191  	}
   192  	if l == 1 {
   193  		return nil
   194  	}
   195  
   196  	i.ranges = make([][2]uint64, 0, l-1)
   197  	for j := 1; j < l; j++ {
   198  		r := bytes.SplitN(d[j], []byte(","), 2)
   199  		if len(r) < 2 {
   200  			return fmt.Errorf("range %d has less then 2 elements", j)
   201  		}
   202  		start, err := strconv.ParseUint(string(r[0]), 36, 64)
   203  		if err != nil {
   204  			return fmt.Errorf("parsing the first element in range %d: %v", j, err)
   205  		}
   206  		end, err := strconv.ParseUint(string(r[1]), 36, 64)
   207  		if err != nil {
   208  			return fmt.Errorf("parsing the second element in range %d: %v", j, err)
   209  		}
   210  		i.ranges = append(i.ranges, [2]uint64{start, end})
   211  	}
   212  
   213  	return nil
   214  }