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  }