summaryrefslogtreecommitdiffstats
path: root/src/internal/trace/v2/batch.go
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-16 19:25:22 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-16 19:25:22 +0000
commitf6ad4dcef54c5ce997a4bad5a6d86de229015700 (patch)
tree7cfa4e31ace5c2bd95c72b154d15af494b2bcbef /src/internal/trace/v2/batch.go
parentInitial commit. (diff)
downloadgolang-1.22-f6ad4dcef54c5ce997a4bad5a6d86de229015700.tar.xz
golang-1.22-f6ad4dcef54c5ce997a4bad5a6d86de229015700.zip
Adding upstream version 1.22.1.upstream/1.22.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/internal/trace/v2/batch.go')
-rw-r--r--src/internal/trace/v2/batch.go97
1 files changed, 97 insertions, 0 deletions
diff --git a/src/internal/trace/v2/batch.go b/src/internal/trace/v2/batch.go
new file mode 100644
index 0000000..899eb0f
--- /dev/null
+++ b/src/internal/trace/v2/batch.go
@@ -0,0 +1,97 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package trace
+
+import (
+ "bufio"
+ "bytes"
+ "encoding/binary"
+ "fmt"
+ "io"
+
+ "internal/trace/v2/event"
+ "internal/trace/v2/event/go122"
+)
+
+// timestamp is an unprocessed timestamp.
+type timestamp uint64
+
+// batch represents a batch of trace events.
+// It is unparsed except for its header.
+type batch struct {
+ m ThreadID
+ time timestamp
+ data []byte
+}
+
+func (b *batch) isStringsBatch() bool {
+ return len(b.data) > 0 && event.Type(b.data[0]) == go122.EvStrings
+}
+
+func (b *batch) isStacksBatch() bool {
+ return len(b.data) > 0 && event.Type(b.data[0]) == go122.EvStacks
+}
+
+func (b *batch) isCPUSamplesBatch() bool {
+ return len(b.data) > 0 && event.Type(b.data[0]) == go122.EvCPUSamples
+}
+
+func (b *batch) isFreqBatch() bool {
+ return len(b.data) > 0 && event.Type(b.data[0]) == go122.EvFrequency
+}
+
+// readBatch reads the next full batch from r.
+func readBatch(r *bufio.Reader) (batch, uint64, error) {
+ // Read batch header byte.
+ b, err := r.ReadByte()
+ if err != nil {
+ return batch{}, 0, err
+ }
+ if typ := event.Type(b); typ != go122.EvEventBatch {
+ return batch{}, 0, fmt.Errorf("expected batch event (%s), got %s", go122.EventString(go122.EvEventBatch), go122.EventString(typ))
+ }
+
+ // Read the batch header: gen (generation), thread (M) ID, base timestamp
+ // for the batch.
+ gen, err := binary.ReadUvarint(r)
+ if err != nil {
+ return batch{}, gen, fmt.Errorf("error reading batch gen: %w", err)
+ }
+ m, err := binary.ReadUvarint(r)
+ if err != nil {
+ return batch{}, gen, fmt.Errorf("error reading batch M ID: %w", err)
+ }
+ ts, err := binary.ReadUvarint(r)
+ if err != nil {
+ return batch{}, gen, fmt.Errorf("error reading batch timestamp: %w", err)
+ }
+
+ // Read in the size of the batch to follow.
+ size, err := binary.ReadUvarint(r)
+ if err != nil {
+ return batch{}, gen, fmt.Errorf("error reading batch size: %w", err)
+ }
+ if size > go122.MaxBatchSize {
+ return batch{}, gen, fmt.Errorf("invalid batch size %d, maximum is %d", size, go122.MaxBatchSize)
+ }
+
+ // Copy out the batch for later processing.
+ var data bytes.Buffer
+ data.Grow(int(size))
+ n, err := io.CopyN(&data, r, int64(size))
+ if n != int64(size) {
+ return batch{}, gen, fmt.Errorf("failed to read full batch: read %d but wanted %d", n, size)
+ }
+ if err != nil {
+ return batch{}, gen, fmt.Errorf("copying batch data: %w", err)
+ }
+
+ // Return the batch.
+ return batch{
+ m: ThreadID(m),
+ time: timestamp(ts),
+ data: data.Bytes(),
+ }, gen, nil
+}