github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/src/dbnode/encoding/series_iterator.go (about) 1 // Copyright (c) 2016 Uber Technologies, Inc. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE. 20 21 package encoding 22 23 import ( 24 "github.com/m3db/m3/src/dbnode/ts" 25 "github.com/m3db/m3/src/x/ident" 26 xtime "github.com/m3db/m3/src/x/time" 27 ) 28 29 type seriesIterator struct { 30 id ident.ID 31 nsID ident.ID 32 tags ident.TagIterator 33 start xtime.UnixNano 34 end xtime.UnixNano 35 iters iterators 36 multiReaderIters []MultiReaderIterator 37 pool SeriesIteratorPool 38 err error 39 firstNext bool 40 closed bool 41 } 42 43 // NewSeriesIterator creates a new series iterator. 44 // NB: The returned SeriesIterator assumes ownership of the provided `ident.ID`. 45 func NewSeriesIterator( 46 opts SeriesIteratorOptions, 47 pool SeriesIteratorPool, 48 ) SeriesIterator { 49 it := &seriesIterator{pool: pool} 50 it.Reset(opts) 51 return it 52 } 53 54 func (it *seriesIterator) ID() ident.ID { 55 return it.id 56 } 57 58 func (it *seriesIterator) Namespace() ident.ID { 59 return it.nsID 60 } 61 62 func (it *seriesIterator) Tags() ident.TagIterator { 63 return it.tags 64 } 65 66 func (it *seriesIterator) Start() xtime.UnixNano { 67 return it.start 68 } 69 70 func (it *seriesIterator) End() xtime.UnixNano { 71 return it.end 72 } 73 74 func (it *seriesIterator) Next() bool { 75 if !it.firstNext { 76 if !it.hasNext() { 77 return false 78 } 79 it.moveToNext() 80 } 81 it.firstNext = false 82 return it.hasNext() 83 } 84 85 func (it *seriesIterator) Current() (ts.Datapoint, xtime.Unit, ts.Annotation) { 86 return it.iters.current() 87 } 88 89 func (it *seriesIterator) Err() error { 90 return it.err 91 } 92 93 func (it *seriesIterator) FirstAnnotation() ts.Annotation { 94 return it.iters.firstAnnotation() 95 } 96 97 func (it *seriesIterator) Close() { 98 if it.isClosed() { 99 return 100 } 101 it.closed = true 102 if it.id != nil { 103 it.id.Finalize() 104 it.id = nil 105 } 106 if it.nsID != nil { 107 it.nsID.Finalize() 108 it.nsID = nil 109 } 110 if it.tags != nil { 111 it.tags.Close() 112 it.tags = nil 113 } 114 115 for idx := range it.multiReaderIters { 116 it.multiReaderIters[idx] = nil 117 } 118 119 it.iters.reset() 120 if it.pool != nil { 121 it.pool.Put(it) 122 } 123 } 124 125 func (it *seriesIterator) Replicas() ([]MultiReaderIterator, error) { 126 return it.multiReaderIters, nil 127 } 128 129 func (it *seriesIterator) Reset(opts SeriesIteratorOptions) { 130 it.id = opts.ID 131 it.nsID = opts.Namespace 132 it.tags = opts.Tags 133 if it.tags == nil { 134 it.tags = ident.EmptyTagIterator 135 } 136 it.multiReaderIters = it.multiReaderIters[:0] 137 it.err = nil 138 it.firstNext = true 139 it.closed = false 140 141 it.iters.closeIters = true 142 it.iters.reset() 143 it.start = opts.StartInclusive 144 it.end = opts.EndExclusive 145 if it.start != 0 && it.end != 0 { 146 it.iters.setFilter(it.start, it.end) 147 } 148 it.SetIterateEqualTimestampStrategy(opts.IterateEqualTimestampStrategy) 149 replicas := opts.Replicas 150 var err error 151 if consolidator := opts.SeriesIteratorConsolidator; consolidator != nil { 152 replicas, err = consolidator.ConsolidateReplicas(replicas) 153 if err != nil { 154 it.err = err 155 return 156 } 157 } 158 159 for _, replica := range replicas { 160 if !replica.Next() || !it.iters.push(replica) { 161 if replica.Err() != nil { 162 it.err = replica.Err() 163 } 164 165 replica.Close() 166 continue 167 } 168 it.multiReaderIters = append(it.multiReaderIters, replica) 169 } 170 } 171 172 func (it *seriesIterator) IterateEqualTimestampStrategy() IterateEqualTimestampStrategy { 173 return it.iters.equalTimesStrategy 174 } 175 176 func (it *seriesIterator) SetIterateEqualTimestampStrategy(strategy IterateEqualTimestampStrategy) { 177 it.iters.equalTimesStrategy = strategy 178 } 179 180 func (it *seriesIterator) hasError() bool { 181 return it.err != nil 182 } 183 184 func (it *seriesIterator) isClosed() bool { 185 return it.closed 186 } 187 188 func (it *seriesIterator) hasMore() bool { 189 return it.iters.len() > 0 190 } 191 192 func (it *seriesIterator) hasNext() bool { 193 return !it.hasError() && !it.isClosed() && it.hasMore() 194 } 195 196 func (it *seriesIterator) moveToNext() { 197 for { 198 prev := it.iters.at() 199 next, err := it.iters.moveToValidNext() 200 if err != nil { 201 it.err = err 202 return 203 } 204 if !next { 205 return 206 } 207 208 curr := it.iters.at() 209 if curr != prev { 210 return 211 } 212 213 // Dedupe by continuing 214 } 215 } 216 217 func (it *seriesIterator) Stats() (SeriesIteratorStats, error) { 218 approx := 0 219 for _, readerIter := range it.multiReaderIters { 220 readers := readerIter.Readers() 221 size, err := readers.Size() 222 if err != nil { 223 return SeriesIteratorStats{}, err 224 } 225 approx += size 226 } 227 return SeriesIteratorStats{ApproximateSizeInBytes: approx}, nil 228 }