golang.org/x/exp@v0.0.0-20240506185415-9bf2ced13842/trace/batch.go (about)

     1  // Copyright 2023 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT.
     6  
     7  //go:build go1.21
     8  
     9  package trace
    10  
    11  import (
    12  	"bytes"
    13  	"encoding/binary"
    14  	"fmt"
    15  	"io"
    16  
    17  	"golang.org/x/exp/trace/internal/event"
    18  	"golang.org/x/exp/trace/internal/event/go122"
    19  )
    20  
    21  // timestamp is an unprocessed timestamp.
    22  type timestamp uint64
    23  
    24  // batch represents a batch of trace events.
    25  // It is unparsed except for its header.
    26  type batch struct {
    27  	m    ThreadID
    28  	time timestamp
    29  	data []byte
    30  }
    31  
    32  func (b *batch) isStringsBatch() bool {
    33  	return len(b.data) > 0 && event.Type(b.data[0]) == go122.EvStrings
    34  }
    35  
    36  func (b *batch) isStacksBatch() bool {
    37  	return len(b.data) > 0 && event.Type(b.data[0]) == go122.EvStacks
    38  }
    39  
    40  func (b *batch) isCPUSamplesBatch() bool {
    41  	return len(b.data) > 0 && event.Type(b.data[0]) == go122.EvCPUSamples
    42  }
    43  
    44  func (b *batch) isFreqBatch() bool {
    45  	return len(b.data) > 0 && event.Type(b.data[0]) == go122.EvFrequency
    46  }
    47  
    48  // readBatch reads the next full batch from r.
    49  func readBatch(r interface {
    50  	io.Reader
    51  	io.ByteReader
    52  }) (batch, uint64, error) {
    53  	// Read batch header byte.
    54  	b, err := r.ReadByte()
    55  	if err != nil {
    56  		return batch{}, 0, err
    57  	}
    58  	if typ := event.Type(b); typ != go122.EvEventBatch {
    59  		return batch{}, 0, fmt.Errorf("expected batch event (%s), got %s", go122.EventString(go122.EvEventBatch), go122.EventString(typ))
    60  	}
    61  
    62  	// Read the batch header: gen (generation), thread (M) ID, base timestamp
    63  	// for the batch.
    64  	gen, err := binary.ReadUvarint(r)
    65  	if err != nil {
    66  		return batch{}, gen, fmt.Errorf("error reading batch gen: %w", err)
    67  	}
    68  	m, err := binary.ReadUvarint(r)
    69  	if err != nil {
    70  		return batch{}, gen, fmt.Errorf("error reading batch M ID: %w", err)
    71  	}
    72  	ts, err := binary.ReadUvarint(r)
    73  	if err != nil {
    74  		return batch{}, gen, fmt.Errorf("error reading batch timestamp: %w", err)
    75  	}
    76  
    77  	// Read in the size of the batch to follow.
    78  	size, err := binary.ReadUvarint(r)
    79  	if err != nil {
    80  		return batch{}, gen, fmt.Errorf("error reading batch size: %w", err)
    81  	}
    82  	if size > go122.MaxBatchSize {
    83  		return batch{}, gen, fmt.Errorf("invalid batch size %d, maximum is %d", size, go122.MaxBatchSize)
    84  	}
    85  
    86  	// Copy out the batch for later processing.
    87  	var data bytes.Buffer
    88  	data.Grow(int(size))
    89  	n, err := io.CopyN(&data, r, int64(size))
    90  	if n != int64(size) {
    91  		return batch{}, gen, fmt.Errorf("failed to read full batch: read %d but wanted %d", n, size)
    92  	}
    93  	if err != nil {
    94  		return batch{}, gen, fmt.Errorf("copying batch data: %w", err)
    95  	}
    96  
    97  	// Return the batch.
    98  	return batch{
    99  		m:    ThreadID(m),
   100  		time: timestamp(ts),
   101  		data: data.Bytes(),
   102  	}, gen, nil
   103  }