github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/src/query/block/scalar.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 block 22 23 import ( 24 "errors" 25 26 "github.com/m3db/m3/src/query/models" 27 xtime "github.com/m3db/m3/src/x/time" 28 ) 29 30 // Scalar is a block containing a single value over a certain bound 31 // This represents constant values; it greatly simplifies downstream operations 32 // by allowing them to treat this as a regular block, while at the same time 33 // having an option to optimize by accessing the scalar value directly instead. 34 type Scalar struct { 35 val float64 36 meta Metadata 37 } 38 39 // NewScalar creates a scalar block whose value is given by the function over 40 // the metadata bounds. 41 func NewScalar( 42 val float64, 43 meta Metadata, 44 ) Block { 45 // NB: sanity check to ensure scalar values always have clean metadata. 46 meta.ResultMetadata = NewResultMetadata() 47 return &Scalar{ 48 val: val, 49 meta: meta, 50 } 51 } 52 53 // Info returns information about the block. 54 func (b *Scalar) Info() BlockInfo { 55 return NewBlockInfo(BlockScalar) 56 } 57 58 // Meta returns the metadata for the block. 59 func (b *Scalar) Meta() Metadata { 60 return b.meta 61 } 62 63 // StepIter returns a step-wise block iterator, giving consolidated values 64 // across all series comprising the box at a single time step. 65 func (b *Scalar) StepIter() (StepIter, error) { 66 bounds := b.meta.Bounds 67 steps := bounds.Steps() 68 return &scalarStepIter{ 69 meta: b.meta, 70 vals: []float64{b.val}, 71 numVals: steps, 72 idx: -1, 73 }, nil 74 } 75 76 // Close closes the block; this is a no-op for scalar block. 77 func (b *Scalar) Close() error { return nil } 78 79 // Value yields the constant value this scalar is set to. 80 func (b *Scalar) Value() float64 { 81 return b.val 82 } 83 84 type scalarStepIter struct { 85 numVals, idx int 86 stepTime xtime.UnixNano 87 err error 88 meta Metadata 89 vals []float64 90 } 91 92 // build an empty SeriesMetadata. 93 func buildSeriesMeta(meta Metadata) SeriesMeta { 94 return SeriesMeta{ 95 Tags: models.NewTags(0, meta.Tags.Opts), 96 } 97 } 98 99 func (it *scalarStepIter) Close() { /* No-op*/ } 100 func (it *scalarStepIter) Err() error { return it.err } 101 func (it *scalarStepIter) StepCount() int { return it.numVals } 102 func (it *scalarStepIter) SeriesMeta() []SeriesMeta { 103 return []SeriesMeta{buildSeriesMeta(it.meta)} 104 } 105 106 func (it *scalarStepIter) Next() bool { 107 if it.err != nil { 108 return false 109 } 110 111 it.idx++ 112 next := it.idx < it.numVals 113 if !next { 114 return false 115 } 116 117 it.stepTime, it.err = it.meta.Bounds.TimeForIndex(it.idx) 118 if it.err != nil { 119 return false 120 } 121 122 return next 123 } 124 125 func (it *scalarStepIter) Current() Step { 126 t := it.stepTime 127 return &scalarStep{ 128 vals: it.vals, 129 time: t, 130 } 131 } 132 133 type scalarStep struct { 134 vals []float64 135 time xtime.UnixNano 136 } 137 138 func (it *scalarStep) Time() xtime.UnixNano { return it.time } 139 func (it *scalarStep) Values() []float64 { return it.vals } 140 141 // SeriesIter is invalid for a scalar block. 142 func (b *Scalar) SeriesIter() (SeriesIter, error) { 143 return nil, errors.New("series iterator undefined for a scalar block") 144 } 145 146 // MultiSeriesIter is invalid for a scalar block. 147 func (b *Scalar) MultiSeriesIter(_ int) ([]SeriesIterBatch, error) { 148 return nil, errors.New("multi series iterator undefined for a scalar block") 149 }