github.com/m3db/m3@v1.5.0/src/query/test/block.go (about) 1 // Copyright (c) 2018 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 test 22 23 import ( 24 "errors" 25 "time" 26 27 "github.com/m3db/m3/src/query/block" 28 "github.com/m3db/m3/src/query/models" 29 "github.com/m3db/m3/src/query/storage" 30 "github.com/m3db/m3/src/query/ts" 31 xtime "github.com/m3db/m3/src/x/time" 32 ) 33 34 type multiSeriesBlock struct { 35 consolidated bool 36 lookbackDuration time.Duration 37 meta block.Metadata 38 seriesList ts.SeriesList 39 query *storage.FetchQuery 40 enableBatched bool 41 } 42 43 func newMultiSeriesBlock( 44 fetchResult *storage.FetchResult, 45 query *storage.FetchQuery, 46 lookbackDuration time.Duration, 47 enableBatched bool, 48 ) block.Block { 49 meta := block.Metadata{ 50 Bounds: models.Bounds{ 51 Start: xtime.ToUnixNano(query.Start), 52 Duration: query.End.Sub(query.Start), 53 StepSize: query.Interval, 54 }, 55 56 ResultMetadata: fetchResult.Metadata, 57 } 58 59 return multiSeriesBlock{ 60 seriesList: fetchResult.SeriesList, 61 meta: meta, 62 lookbackDuration: lookbackDuration, 63 enableBatched: enableBatched, 64 query: query, 65 } 66 } 67 68 func (m multiSeriesBlock) Meta() block.Metadata { 69 return m.meta 70 } 71 72 func (m multiSeriesBlock) StepCount() int { 73 // If series has fewer points then it should return NaNs 74 return m.meta.Bounds.Steps() 75 } 76 77 func (m multiSeriesBlock) StepIter() (block.StepIter, error) { 78 return nil, errors.New("step iterator is not supported by test block") 79 } 80 81 func (m multiSeriesBlock) SeriesIter() (block.SeriesIter, error) { 82 return newMultiSeriesBlockSeriesIter(m), nil 83 } 84 85 func (m multiSeriesBlock) MultiSeriesIter( 86 concurrency int, 87 ) ([]block.SeriesIterBatch, error) { 88 if !m.enableBatched { 89 return nil, 90 errors.New("batched iterator is not supported by this test block") 91 } 92 93 batches := make([]ts.SeriesList, 0, concurrency) 94 for i := 0; i < concurrency; i++ { 95 batches = append(batches, make(ts.SeriesList, 0, 10)) 96 } 97 98 // round-robin series. 99 for i, seriesList := range m.seriesList { 100 batches[i%concurrency] = append(batches[i%concurrency], seriesList) 101 } 102 103 seriesIterBatches := make([]block.SeriesIterBatch, 0, concurrency) 104 for _, batch := range batches { 105 insideBlock := newMultiSeriesBlock(&storage.FetchResult{ 106 SeriesList: batch, 107 Metadata: m.meta.ResultMetadata, 108 }, m.query, m.lookbackDuration, false) 109 it, err := insideBlock.SeriesIter() 110 if err != nil { 111 return nil, err 112 } 113 114 seriesIterBatches = append(seriesIterBatches, block.SeriesIterBatch{ 115 Iter: it, 116 Size: len(batch), 117 }) 118 } 119 120 return seriesIterBatches, nil 121 } 122 123 func (m multiSeriesBlock) SeriesMeta() []block.SeriesMeta { 124 metas := make([]block.SeriesMeta, len(m.seriesList)) 125 for i, s := range m.seriesList { 126 metas[i].Tags = s.Tags 127 metas[i].Name = s.Name() 128 } 129 130 return metas 131 } 132 133 func (m multiSeriesBlock) Info() block.BlockInfo { 134 return block.NewBlockInfo(block.BlockTest) 135 } 136 137 // TODO: Actually free up resources 138 func (m multiSeriesBlock) Close() error { 139 return nil 140 } 141 142 type multiSeriesBlockSeriesIter struct { 143 block multiSeriesBlock 144 index int 145 consolidated bool 146 } 147 148 func (m *multiSeriesBlockSeriesIter) SeriesMeta() []block.SeriesMeta { 149 return m.block.SeriesMeta() 150 } 151 152 func newMultiSeriesBlockSeriesIter( 153 block multiSeriesBlock, 154 ) block.SeriesIter { 155 return &multiSeriesBlockSeriesIter{ 156 block: block, 157 index: -1, 158 consolidated: block.consolidated, 159 } 160 } 161 162 func (m *multiSeriesBlockSeriesIter) SeriesCount() int { 163 return len(m.block.seriesList) 164 } 165 166 func (m *multiSeriesBlockSeriesIter) Next() bool { 167 m.index++ 168 return m.index < m.SeriesCount() 169 } 170 171 func (m *multiSeriesBlockSeriesIter) Current() block.UnconsolidatedSeries { 172 s := m.block.seriesList[m.index] 173 return block.NewUnconsolidatedSeries( 174 s.Values().Datapoints(), 175 block.SeriesMeta{ 176 Tags: s.Tags, 177 Name: s.Name(), 178 }, 179 block.UnconsolidatedSeriesStats{Enabled: true}, 180 ) 181 } 182 183 func (m *multiSeriesBlockSeriesIter) Err() error { 184 return nil 185 } 186 187 func (m *multiSeriesBlockSeriesIter) Close() { 188 }