github.com/siglens/siglens@v0.0.0-20240328180423-f7ce9ae441ed/pkg/segment/writer/metrics/compress/decompressor.go (about) 1 /* 2 Copyright 2023. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package compress 18 19 import ( 20 "errors" 21 "fmt" 22 "io" 23 "math" 24 ) 25 26 // Compressor decompresses time-series data based on Facebook's paper. 27 // Link to the paper: https://www.vldb.org/pvldb/vol8/p1816-teller.pdf 28 type Decompressor struct { 29 br *bitReader 30 header uint32 31 t uint32 32 delta uint32 33 leadingZeros uint8 34 trailingZeros uint8 35 value uint64 36 } 37 38 // NewDecompressIterator initializes Decompressor and returns decompressed header. 39 func NewDecompressIterator(r io.Reader) (*DecompressIterator, error) { 40 d := &Decompressor{ 41 br: newBitReader(r), 42 } 43 h, err := d.br.readBits(32) 44 if err != nil { 45 return nil, err 46 } 47 d.header = uint32(h) 48 return &DecompressIterator{0, 0, nil, d}, nil 49 } 50 51 // Iterator returns an iterator of decompressor. 52 func (d *Decompressor) Iterator() *DecompressIterator { 53 return &DecompressIterator{0, 0, nil, d} 54 } 55 56 // DecompressIterator is an iterator of Decompressor. 57 type DecompressIterator struct { 58 t uint32 59 v float64 60 err error 61 d *Decompressor 62 } 63 64 // At returns decompressed time-series data. 65 func (di *DecompressIterator) At() (t uint32, v float64) { 66 return di.t, di.v 67 } 68 69 // Err returns error during decompression. 70 func (di *DecompressIterator) Err() error { 71 if errors.Is(di.err, io.EOF) { 72 return nil 73 } 74 return di.err 75 } 76 77 // Next proceeds decompressing time-series data unitil EOF. 78 func (di *DecompressIterator) Next() bool { 79 if di.d.t == 0 { 80 di.t, di.v, di.err = di.d.decompressFirst() 81 } else { 82 di.t, di.v, di.err = di.d.decompress() 83 } 84 return di.err == nil 85 } 86 87 func (d *Decompressor) decompressFirst() (t uint32, v float64, err error) { 88 delta, err := d.br.readBits(firstDeltaBits) 89 if err != nil { 90 return 0, 0, fmt.Errorf("failed to decompress delta at first: %w", err) 91 } 92 if delta == 1<<firstDeltaBits-1 { 93 return 0, 0, io.EOF 94 } 95 96 value, err := d.br.readBits(64) 97 if err != nil { 98 return 0, 0, fmt.Errorf("failed to decompress value at first: %w", err) 99 } 100 101 d.delta = uint32(delta) 102 d.t = d.header + d.delta 103 d.value = value 104 105 return d.t, math.Float64frombits(d.value), nil 106 } 107 108 func (d *Decompressor) decompress() (t uint32, v float64, err error) { 109 t, err = d.decompressTimestamp() 110 if err != nil { 111 return 0, 0, err 112 } 113 114 v, err = d.decompressValue() 115 if err != nil { 116 return 0, 0, err 117 } 118 119 return t, v, nil 120 } 121 122 func (d *Decompressor) decompressTimestamp() (uint32, error) { 123 n, err := d.dodTimestampBitN() 124 if err != nil { 125 return 0, err 126 } 127 128 if n == 0 { 129 d.t += d.delta 130 return d.t, nil 131 } 132 133 bits, err := d.br.readBits(int(n)) 134 if err != nil { 135 return 0, fmt.Errorf("failed to read timestamp: %w", err) 136 } 137 138 if n == 32 && bits == 0xFFFFFFFF { 139 return 0, io.EOF 140 } 141 142 var dod int64 = int64(bits) 143 if n != 32 && 1<<(n-1) < int64(bits) { 144 dod = int64(bits - 1<<n) 145 } 146 147 d.delta += uint32(dod) 148 d.t += d.delta 149 return d.t, nil 150 } 151 152 // returning the amount of delta-of-delta timestamp bits. 153 func (d *Decompressor) dodTimestampBitN() (n uint, err error) { 154 var dod byte 155 for i := 0; i < 4; i++ { 156 dod <<= 1 157 b, err := d.br.readBit() 158 if err != nil { 159 return 0, err 160 } 161 if b { 162 dod |= 1 163 } else { 164 break 165 } 166 } 167 168 switch dod { 169 case 0x00: // 0 170 return 0, nil 171 case 0x02: // 10 172 return 7, nil 173 case 0x06: // 110 174 return 9, nil 175 case 0x0E: // 1110 176 return 12, nil 177 case 0x0F: // 1111 178 return 32, nil 179 default: 180 return 0, errors.New("invalid bit header for bit length to read") 181 } 182 } 183 184 func (d *Decompressor) decompressValue() (float64, error) { 185 var read byte 186 for i := 0; i < 2; i++ { 187 bit, err := d.br.readBit() 188 if err != nil { 189 return 0, fmt.Errorf("failed to read value: %w", err) 190 } 191 if bit { 192 read <<= 1 193 read++ 194 } else { 195 break 196 } 197 } 198 if read == 0x1 || read == 0x3 { // read byte is '1' or '11' 199 if read == 0x3 { // read byte is '11' 200 leadingZeros, err := d.br.readBits(5) 201 if err != nil { 202 return 0, fmt.Errorf("failed to read value: %w", err) 203 } 204 significantBits, err := d.br.readBits(6) 205 if err != nil { 206 return 0, fmt.Errorf("failed to read value: %w", err) 207 } 208 if significantBits == 0 { 209 significantBits = 64 210 } 211 d.leadingZeros = uint8(leadingZeros) 212 d.trailingZeros = 64 - uint8(significantBits) - d.leadingZeros 213 } 214 // read byte is '11' or '1' 215 valueBits, err := d.br.readBits(int(64 - d.leadingZeros - d.trailingZeros)) 216 if err != nil { 217 return 0, fmt.Errorf("failed to read value: %w", err) 218 } 219 valueBits <<= uint64(d.trailingZeros) 220 d.value ^= valueBits 221 } 222 return math.Float64frombits(d.value), nil 223 }