1
2
3
4
5 package trace
6
7 import (
8 "bytes"
9 "encoding/binary"
10 "fmt"
11 "io"
12
13 "internal/trace/event"
14 "internal/trace/event/go122"
15 )
16
17
18 type timestamp uint64
19
20
21
22 type batch struct {
23 m ThreadID
24 time timestamp
25 data []byte
26 exp event.Experiment
27 }
28
29 func (b *batch) isStringsBatch() bool {
30 return b.exp == event.NoExperiment && len(b.data) > 0 && event.Type(b.data[0]) == go122.EvStrings
31 }
32
33 func (b *batch) isStacksBatch() bool {
34 return b.exp == event.NoExperiment && len(b.data) > 0 && event.Type(b.data[0]) == go122.EvStacks
35 }
36
37 func (b *batch) isCPUSamplesBatch() bool {
38 return b.exp == event.NoExperiment && len(b.data) > 0 && event.Type(b.data[0]) == go122.EvCPUSamples
39 }
40
41 func (b *batch) isFreqBatch() bool {
42 return b.exp == event.NoExperiment && len(b.data) > 0 && event.Type(b.data[0]) == go122.EvFrequency
43 }
44
45
46 func readBatch(r interface {
47 io.Reader
48 io.ByteReader
49 }) (batch, uint64, error) {
50
51 b, err := r.ReadByte()
52 if err != nil {
53 return batch{}, 0, err
54 }
55 if typ := event.Type(b); typ != go122.EvEventBatch && typ != go122.EvExperimentalBatch {
56 return batch{}, 0, fmt.Errorf("expected batch event, got %s", go122.EventString(typ))
57 }
58
59
60 exp := event.NoExperiment
61 if event.Type(b) == go122.EvExperimentalBatch {
62 e, err := r.ReadByte()
63 if err != nil {
64 return batch{}, 0, err
65 }
66 exp = event.Experiment(e)
67 }
68
69
70
71 gen, err := binary.ReadUvarint(r)
72 if err != nil {
73 return batch{}, gen, fmt.Errorf("error reading batch gen: %w", err)
74 }
75 m, err := binary.ReadUvarint(r)
76 if err != nil {
77 return batch{}, gen, fmt.Errorf("error reading batch M ID: %w", err)
78 }
79 ts, err := binary.ReadUvarint(r)
80 if err != nil {
81 return batch{}, gen, fmt.Errorf("error reading batch timestamp: %w", err)
82 }
83
84
85 size, err := binary.ReadUvarint(r)
86 if err != nil {
87 return batch{}, gen, fmt.Errorf("error reading batch size: %w", err)
88 }
89 if size > go122.MaxBatchSize {
90 return batch{}, gen, fmt.Errorf("invalid batch size %d, maximum is %d", size, go122.MaxBatchSize)
91 }
92
93
94 var data bytes.Buffer
95 data.Grow(int(size))
96 n, err := io.CopyN(&data, r, int64(size))
97 if n != int64(size) {
98 return batch{}, gen, fmt.Errorf("failed to read full batch: read %d but wanted %d", n, size)
99 }
100 if err != nil {
101 return batch{}, gen, fmt.Errorf("copying batch data: %w", err)
102 }
103
104
105 return batch{
106 m: ThreadID(m),
107 time: timestamp(ts),
108 data: data.Bytes(),
109 exp: exp,
110 }, gen, nil
111 }
112
View as plain text