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 }