github.com/turingchain2020/turingchain@v1.1.21/common/db/merge_iter.go (about)

     1  package db
     2  
     3  //合并两个迭代器成一个迭代器
     4  
     5  import (
     6  	"errors"
     7  
     8  	"github.com/syndtr/goleveldb/leveldb/comparer"
     9  )
    10  
    11  type dir int
    12  
    13  const (
    14  	dirReleased dir = iota - 1
    15  	dirSOI
    16  	dirEOI
    17  	dirForward
    18  	dirSeek
    19  )
    20  
    21  //合并错误列表
    22  var (
    23  	ErrIterReleased = errors.New("ErrIterReleased")
    24  )
    25  
    26  type mergedIterator struct {
    27  	itBase
    28  	cmp     comparer.Comparer
    29  	iters   []Iterator
    30  	strict  bool
    31  	reverse bool
    32  	keys    [][]byte
    33  	prevKey []byte
    34  	index   int
    35  	dir     dir
    36  	err     error
    37  }
    38  
    39  func assertKey(key []byte) []byte {
    40  	if key == nil {
    41  		panic("leveldb/iterator: nil key")
    42  	}
    43  	return key
    44  }
    45  
    46  func (i *mergedIterator) iterErr(iter Iterator) bool {
    47  	if err := iter.Error(); err != nil {
    48  		if i.strict {
    49  			i.err = err
    50  			return true
    51  		}
    52  	}
    53  	return false
    54  }
    55  
    56  func (i *mergedIterator) Valid() bool {
    57  	return i.err == nil && i.dir > dirEOI
    58  }
    59  
    60  func (i *mergedIterator) Rewind() bool {
    61  	if i.err != nil {
    62  		return false
    63  	} else if i.dir == dirReleased {
    64  		i.err = ErrIterReleased
    65  		return false
    66  	}
    67  
    68  	for x, iter := range i.iters {
    69  		switch {
    70  		case iter.Rewind():
    71  			i.keys[x] = assertKey(iter.Key())
    72  		case i.iterErr(iter):
    73  			return false
    74  		default:
    75  			i.keys[x] = nil
    76  		}
    77  	}
    78  	i.dir = dirSOI
    79  	return i.next(false)
    80  }
    81  
    82  func (i *mergedIterator) Seek(key []byte) bool {
    83  	if i.err != nil {
    84  		return false
    85  	} else if i.dir == dirReleased {
    86  		i.err = ErrIterReleased
    87  		return false
    88  	}
    89  	for x, iter := range i.iters {
    90  		switch {
    91  		case iter.Seek(key):
    92  			i.keys[x] = assertKey(iter.Key())
    93  		case i.iterErr(iter):
    94  			return false
    95  		default:
    96  			i.keys[x] = nil
    97  		}
    98  	}
    99  	i.dir = dirSOI
   100  	if i.next(true) {
   101  		i.dir = dirSeek
   102  		return true
   103  	}
   104  	i.dir = dirSOI
   105  	return false
   106  }
   107  
   108  func (i *mergedIterator) compare(tkey []byte, key []byte, ignoreReverse bool) int {
   109  	if ignoreReverse {
   110  		return i.cmp.Compare(tkey, key)
   111  	}
   112  	if tkey == nil && key != nil {
   113  		return 1
   114  	}
   115  	if tkey != nil && key == nil {
   116  		return -1
   117  	}
   118  	result := i.cmp.Compare(tkey, key)
   119  	if i.reverse {
   120  		return -result
   121  	}
   122  	return result
   123  }
   124  
   125  func (i *mergedIterator) next(ignoreReverse bool) bool {
   126  	var key []byte
   127  	for x, tkey := range i.keys {
   128  		if tkey != nil && (key == nil || i.compare(tkey, key, ignoreReverse) < 0) {
   129  			key = tkey
   130  			i.index = x
   131  		}
   132  	}
   133  	if key == nil {
   134  		i.dir = dirEOI
   135  		return false
   136  	}
   137  	if i.dir == dirSOI {
   138  		i.prevKey = cloneByte(key)
   139  	}
   140  	i.dir = dirForward
   141  	return true
   142  }
   143  
   144  func (i *mergedIterator) Next() bool {
   145  	for {
   146  		ok, isrewind := i.nextInternal()
   147  		if !ok {
   148  			break
   149  		}
   150  		if isrewind {
   151  			return true
   152  		}
   153  		if i.compare(i.Key(), i.prevKey, true) != 0 {
   154  			i.prevKey = cloneByte(i.Key())
   155  			return true
   156  		}
   157  	}
   158  	return false
   159  }
   160  
   161  func (i *mergedIterator) nextInternal() (bool, bool) {
   162  	if i.dir == dirEOI || i.err != nil {
   163  		return false, false
   164  	} else if i.dir == dirReleased {
   165  		i.err = ErrIterReleased
   166  		return false, false
   167  	}
   168  	switch i.dir {
   169  	case dirSOI:
   170  		return i.Rewind(), true
   171  	case dirSeek:
   172  		if !i.reverse {
   173  			break
   174  		}
   175  		key := append([]byte{}, i.keys[i.index]...)
   176  		for x, iter := range i.iters {
   177  			if x == i.index {
   178  				continue
   179  			}
   180  			seek := iter.Seek(key)
   181  			switch {
   182  			case seek && iter.Next(), !seek && iter.Rewind():
   183  				i.keys[x] = assertKey(iter.Key())
   184  			case i.iterErr(iter):
   185  				return false, false
   186  			default:
   187  				i.keys[x] = nil
   188  			}
   189  		}
   190  	}
   191  	x := i.index
   192  	iter := i.iters[x]
   193  	switch {
   194  	case iter.Next():
   195  		i.keys[x] = assertKey(iter.Key())
   196  	case i.iterErr(iter):
   197  		return false, false
   198  	default:
   199  		i.keys[x] = nil
   200  	}
   201  	return i.next(false), false
   202  }
   203  
   204  func (i *mergedIterator) Key() []byte {
   205  	if i.err != nil || i.dir <= dirEOI {
   206  		return nil
   207  	}
   208  	return i.keys[i.index]
   209  }
   210  
   211  func (i *mergedIterator) Value() []byte {
   212  	if i.err != nil || i.dir <= dirEOI {
   213  		return nil
   214  	}
   215  	return i.iters[i.index].Value()
   216  }
   217  
   218  func (i *mergedIterator) ValueCopy() []byte {
   219  	if i.err != nil || i.dir <= dirEOI {
   220  		return nil
   221  	}
   222  	v := i.iters[i.index].Value()
   223  	return cloneByte(v)
   224  }
   225  
   226  func (i *mergedIterator) Close() {
   227  	if i.dir != dirReleased {
   228  		i.dir = dirReleased
   229  		for _, iter := range i.iters {
   230  			iter.Close()
   231  		}
   232  		i.iters = nil
   233  		i.keys = nil
   234  	}
   235  }
   236  
   237  func (i *mergedIterator) Error() error {
   238  	return i.err
   239  }
   240  
   241  // NewMergedIterator returns an iterator that merges its input. Walking the
   242  // resultant iterator will return all key/value pairs of all input iterators
   243  // in strictly increasing key order, as defined by cmp.
   244  // The input's key ranges may overlap, but there are assumed to be no duplicate
   245  // keys: if iters[i] contains a key k then iters[j] will not contain that key k.
   246  // None of the iters may be nil.
   247  //
   248  // If strict is true the any 'corruption errors' (i.e errors.IsCorrupted(err) == true)
   249  // won't be ignored and will halt 'merged iterator', otherwise the iterator will
   250  // continue to the next 'input iterator'.
   251  func NewMergedIterator(iters []Iterator) Iterator {
   252  	reverse := true
   253  	if len(iters) >= 2 {
   254  		reverse = iters[0].IsReverse()
   255  		for i := 1; i < len(iters); i++ {
   256  			if reverse != iters[i].IsReverse() {
   257  				panic("merge iter not support diff reverse flag")
   258  			}
   259  		}
   260  	}
   261  	return &mergedIterator{
   262  		iters:   iters,
   263  		reverse: reverse,
   264  		cmp:     comparer.DefaultComparer,
   265  		strict:  true,
   266  		keys:    make([][]byte, len(iters)),
   267  	}
   268  }
   269  
   270  type mergedIteratorDB struct {
   271  	iters []IteratorDB
   272  }
   273  
   274  //NewMergedIteratorDB 合并两个迭代数据库
   275  func NewMergedIteratorDB(iters []IteratorDB) IteratorDB {
   276  	return &mergedIteratorDB{iters: iters}
   277  }
   278  
   279  func (merge *mergedIteratorDB) Iterator(start []byte, end []byte, reverse bool) Iterator {
   280  	iters := make([]Iterator, len(merge.iters))
   281  	for i := 0; i < len(merge.iters); i++ {
   282  		iters[i] = merge.iters[i].Iterator(start, end, reverse)
   283  	}
   284  	return NewMergedIterator(iters)
   285  }