github.com/hyperledger/burrow@v0.34.5-0.20220512172541-77f09336001d/forensics/storage/channel_iterator.go (about)

     1  package storage
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"sort"
     7  )
     8  
     9  type ChannelIterator struct {
    10  	ch      <-chan KVPair
    11  	start   []byte
    12  	end     []byte
    13  	kv      KVPair
    14  	invalid bool
    15  }
    16  
    17  type KVPair struct {
    18  	Key   []byte
    19  	Value []byte
    20  }
    21  
    22  func (kv KVPair) String() string {
    23  	return fmt.Sprintf("%s => %s", string(kv.Key), string(kv.Value))
    24  }
    25  
    26  type KVPairs []KVPair
    27  
    28  func (kvp KVPairs) Len() int {
    29  	return len(kvp)
    30  }
    31  
    32  func (kvp KVPairs) Less(i, j int) bool {
    33  	return bytes.Compare(kvp[i].Key, kvp[j].Key) == -1
    34  }
    35  
    36  func (kvp KVPairs) Swap(i, j int) {
    37  	kvp[i], kvp[j] = kvp[j], kvp[i]
    38  }
    39  
    40  func (kvp KVPairs) Sorted() KVPairs {
    41  	kvpCopy := make(KVPairs, len(kvp))
    42  	copy(kvpCopy, kvp)
    43  	sort.Stable(kvpCopy)
    44  	return kvpCopy
    45  }
    46  
    47  // ChannelIterator wraps a stream of kvp KVPairs over a channel as a stateful KVIterator. The start and end keys provided
    48  // are purely indicative (for Domain()) and are assumed to be honoured by the input channel - they are not checked
    49  // and keys are not sorted. NewChannelIterator will block until the first value is received over the channel.
    50  func NewChannelIterator(ch <-chan KVPair, start, end []byte) *ChannelIterator {
    51  	ci := &ChannelIterator{
    52  		ch:    ch,
    53  		start: start,
    54  		end:   end,
    55  	}
    56  	// Load first element if it exists
    57  	ci.Next()
    58  	return ci
    59  }
    60  
    61  func (it *ChannelIterator) Domain() ([]byte, []byte) {
    62  	return it.start, it.end
    63  }
    64  
    65  func (it *ChannelIterator) Valid() bool {
    66  	return !it.invalid
    67  }
    68  
    69  func (it *ChannelIterator) Next() {
    70  	if it.invalid {
    71  		panic("ChannelIterator.Value() called on invalid iterator")
    72  	}
    73  	kv, ok := <-it.ch
    74  	it.invalid = !ok
    75  	it.kv = kv
    76  }
    77  
    78  func (it *ChannelIterator) Key() []byte {
    79  	if it.invalid {
    80  		panic("ChannelIterator.Key() called on invalid iterator")
    81  	}
    82  	return it.kv.Key
    83  }
    84  
    85  func (it *ChannelIterator) Value() []byte {
    86  	if it.invalid {
    87  		panic("ChannelIterator.Value() called on invalid iterator")
    88  	}
    89  	return it.kv.Value
    90  }
    91  
    92  func (it *ChannelIterator) Close() error {
    93  	for range it.ch {
    94  		// drain channel if necessary
    95  	}
    96  	return nil
    97  }
    98  
    99  func (it *ChannelIterator) Error() error {
   100  	for range it.ch {
   101  		if err := it.Error(); err != nil {
   102  			return nil
   103  		}
   104  	}
   105  	return nil
   106  }