github.com/pyroscope-io/pyroscope@v0.37.3-0.20230725203016-5f6947968bd0/pkg/storage/segment/serialization.go (about)

     1  package segment
     2  
     3  import (
     4  	"bufio"
     5  	"bytes"
     6  	"errors"
     7  	"io"
     8  	"time"
     9  
    10  	"github.com/pyroscope-io/pyroscope/pkg/storage/metadata"
    11  	"github.com/pyroscope-io/pyroscope/pkg/util/serialization"
    12  	"github.com/pyroscope-io/pyroscope/pkg/util/varint"
    13  )
    14  
    15  // serialization format version. it's not very useful right now, but it will be in the future
    16  const currentVersion = 3
    17  
    18  func (s *Segment) populateFromMetadata(mdata map[string]interface{}) {
    19  	if v, ok := mdata["sampleRate"]; ok {
    20  		s.sampleRate = uint32(v.(float64))
    21  	}
    22  	if v, ok := mdata["spyName"]; ok {
    23  		s.spyName = v.(string)
    24  	}
    25  	if v, ok := mdata["units"]; ok {
    26  		s.units = metadata.Units(v.(string))
    27  	}
    28  	if v, ok := mdata["aggregationType"]; ok {
    29  		s.aggregationType = metadata.AggregationType(v.(string))
    30  	}
    31  }
    32  
    33  func (s *Segment) generateMetadata() map[string]interface{} {
    34  	return map[string]interface{}{
    35  		"sampleRate":      s.sampleRate,
    36  		"spyName":         s.spyName,
    37  		"units":           s.units,
    38  		"aggregationType": s.aggregationType,
    39  	}
    40  }
    41  
    42  func (s *Segment) Serialize(w io.Writer) error {
    43  	s.m.RLock()
    44  	defer s.m.RUnlock()
    45  
    46  	vw := varint.NewWriter()
    47  	if _, err := vw.Write(w, currentVersion); err != nil {
    48  		return err
    49  	}
    50  	if err := serialization.WriteMetadata(w, s.generateMetadata()); err != nil {
    51  		return err
    52  	}
    53  
    54  	if s.root == nil {
    55  		return nil
    56  	}
    57  
    58  	s.serialize(w, vw, s.root)
    59  
    60  	return s.watermarks.serialize(w)
    61  }
    62  
    63  func (s *Segment) serialize(w io.Writer, vw varint.Writer, n *streeNode) {
    64  	vw.Write(w, uint64(n.depth))
    65  	vw.Write(w, uint64(n.time.Unix()))
    66  	vw.Write(w, n.samples)
    67  	vw.Write(w, n.writes)
    68  	p := uint64(0)
    69  	if n.present {
    70  		p = 1
    71  	}
    72  	vw.Write(w, p)
    73  
    74  	// depth
    75  	// time
    76  	// keyInChunks
    77  	// children
    78  	l := 0
    79  	for _, v := range n.children {
    80  		if v != nil {
    81  			l++
    82  		}
    83  	}
    84  
    85  	vw.Write(w, uint64(l))
    86  	for _, v := range n.children {
    87  		if v != nil {
    88  			s.serialize(w, vw, v)
    89  		}
    90  	}
    91  }
    92  
    93  var errMaxDepth = errors.New("depth is too high")
    94  
    95  func Deserialize(r io.Reader) (*Segment, error) {
    96  	s := New()
    97  	br := bufio.NewReader(r) // TODO if it's already a bytereader skip
    98  
    99  	// reads serialization format version, see comment at the top
   100  	version, err := varint.Read(br)
   101  	if err != nil {
   102  		return nil, err
   103  	}
   104  
   105  	mdata, err := serialization.ReadMetadata(br)
   106  	if err != nil {
   107  		return nil, err
   108  	}
   109  	s.populateFromMetadata(mdata)
   110  
   111  	// In some cases, there can be no nodes.
   112  	if br.Buffered() == 0 {
   113  		return s, nil
   114  	}
   115  
   116  	parents := []*streeNode{nil}
   117  	for len(parents) > 0 {
   118  		depth, err := varint.Read(br)
   119  		if err != nil {
   120  			return nil, err
   121  		}
   122  		if int(depth) >= len(durations) {
   123  			return nil, errMaxDepth
   124  		}
   125  		timeVal, err := varint.Read(br)
   126  		if err != nil {
   127  			return nil, err
   128  		}
   129  		samplesVal, err := varint.Read(br)
   130  		if err != nil {
   131  			return nil, err
   132  		}
   133  		var writesVal uint64
   134  		if version >= 2 {
   135  			writesVal, err = varint.Read(br)
   136  			if err != nil {
   137  				return nil, err
   138  			}
   139  		}
   140  		presentVal, err := varint.Read(br)
   141  		if err != nil {
   142  			return nil, err
   143  		}
   144  		node := newNode(time.Unix(int64(timeVal), 0), int(depth), multiplier)
   145  		if presentVal == 1 {
   146  			node.present = true
   147  		}
   148  		node.samples = samplesVal
   149  		node.writes = writesVal
   150  		if s.root == nil {
   151  			s.root = node
   152  		}
   153  
   154  		parent := parents[0]
   155  		parents = parents[1:]
   156  		if parent != nil {
   157  			parent.replace(node)
   158  		}
   159  		childrenLen, err := varint.Read(br)
   160  		if err != nil {
   161  			return nil, err
   162  		}
   163  
   164  		r := []*streeNode{}
   165  		for i := 0; i < int(childrenLen); i++ {
   166  			r = append(r, node)
   167  		}
   168  		parents = append(r, parents...)
   169  	}
   170  
   171  	if version >= 3 {
   172  		if err = deserializeWatermarks(br, &s.watermarks); err != nil {
   173  			return nil, err
   174  		}
   175  	}
   176  
   177  	return s, nil
   178  }
   179  
   180  func (s *Segment) Bytes() ([]byte, error) {
   181  	b := bytes.Buffer{}
   182  	if err := s.Serialize(&b); err != nil {
   183  		return nil, err
   184  	}
   185  	return b.Bytes(), nil
   186  }
   187  
   188  func FromBytes(p []byte) (*Segment, error) {
   189  	return Deserialize(bytes.NewReader(p))
   190  }
   191  
   192  func (w watermarks) serialize(dst io.Writer) error {
   193  	vw := varint.NewWriter()
   194  	if _, err := vw.Write(dst, uint64(w.absoluteTime.UTC().Unix())); err != nil {
   195  		return err
   196  	}
   197  	if _, err := vw.Write(dst, uint64(len(w.levels))); err != nil {
   198  		return err
   199  	}
   200  	for k, v := range w.levels {
   201  		if _, err := vw.Write(dst, uint64(k)); err != nil {
   202  			return err
   203  		}
   204  		if _, err := vw.Write(dst, uint64(v.UTC().Unix())); err != nil {
   205  			return err
   206  		}
   207  	}
   208  	return nil
   209  }
   210  
   211  func deserializeWatermarks(r io.ByteReader, w *watermarks) error {
   212  	a, err := varint.Read(r)
   213  	if err != nil {
   214  		return err
   215  	}
   216  	w.absoluteTime = time.Unix(int64(a), 0).UTC()
   217  	l, err := varint.Read(r)
   218  	if err != nil {
   219  		return err
   220  	}
   221  	levels := int(l)
   222  	for i := 0; i < levels; i++ {
   223  		k, err := varint.Read(r)
   224  		if err != nil {
   225  			return err
   226  		}
   227  		v, err := varint.Read(r)
   228  		if err != nil {
   229  			return err
   230  		}
   231  		w.levels[int(k)] = time.Unix(int64(v), 0).UTC()
   232  	}
   233  	return nil
   234  }