Skip to content

Commit 4add732

Browse files
committed
resuable read buffers for codec and godoc
1 parent 252360c commit 4add732

1 file changed

Lines changed: 25 additions & 14 deletions

File tree

segment_codec.go

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,17 @@ import (
2525
)
2626

2727
const (
28+
// Maximum size of a segment payload in bytes
2829
maxSegmentPayloadSize = 1<<17 - 1
2930

30-
compressedHeaderSize = 5 + crc24Size
31+
// Size of compressed segment header in bytes
32+
compressedHeaderSize = 5 + crc24Size
33+
// Size of uncompressed segment header in bytes
3134
uncompressedHeaderSize = 3 + crc24Size
3235

36+
// Size of header checksum in bytes
3337
crc24Size = 3
38+
// Size of payload checksum in bytes
3439
crc32Size = 4
3540
)
3641

@@ -51,9 +56,17 @@ func (segment *segmentHeader) String() string {
5156
segment.isSelfContained)
5257
}
5358

59+
// segmentCodec is responsible for encoding and decoding segments.
60+
// It supports both compressed and uncompressed segment formats.
61+
// Decode path is not thread safe as it uses reusable buffers for decoding segment header and payload crc32.
62+
// It is expected to be used within a single instance of [Conn].
5463
type segmentCodec struct {
5564
compressor Compressor
5665
compressed bool
66+
// Reusable buffer for decoding segment header, at most 8 bytes
67+
readHeaderBuf [compressedHeaderSize]byte
68+
// Reusable buffer for decoding segment payload crc32, at most 4 bytes
69+
readChecksumBuf [crc32Size]byte
5770
}
5871

5972
func newSegmentCodec(compressor Compressor) segmentCodec {
@@ -108,7 +121,7 @@ func (sc *segmentCodec) encodeCompressedSegmentHeader(compressedLen, uncompresse
108121
combined |= 1 << 34
109122
}
110123

111-
binary.LittleEndian.PutUint64(dest[:], combined)
124+
binary.LittleEndian.PutUint64(dest, combined)
112125

113126
headerCRC24 := Crc24(dest[:5])
114127
dest[5] = byte(headerCRC24)
@@ -224,9 +237,8 @@ func (sc *segmentCodec) verifySegmentPayloadChecksum(data []byte, expected uint3
224237

225238
// decodeCompressedSegmentHeader reads and verifies the header of a compressed segment from the given reader.
226239
func (sc *segmentCodec) decodeCompressedSegmentHeader(r io.Reader) (*segmentHeader, error) {
227-
var headerBuf [8]byte // TODO: potentially optimize allocation, could be stored in segmentCodec and reused if the codec is a specific for each Conn
228-
229-
if _, err := io.ReadFull(r, headerBuf[:8]); err != nil {
240+
headerBuf := sc.readHeaderBuf[:compressedHeaderSize]
241+
if _, err := io.ReadFull(r, headerBuf); err != nil {
230242
return nil, err
231243
}
232244

@@ -249,19 +261,18 @@ func (sc *segmentCodec) decodeCompressedSegmentHeader(r io.Reader) (*segmentHead
249261

250262
// decodeUncompressedSegmentHeader reads and verifies the header of an uncompressed segment from the given reader.
251263
func (sc *segmentCodec) decodeUncompressedSegmentHeader(r io.Reader) (*segmentHeader, error) {
252-
var header [6]byte
253-
254-
if _, err := io.ReadFull(r, header[:]); err != nil {
264+
headerBuf := sc.readHeaderBuf[:uncompressedHeaderSize]
265+
if _, err := io.ReadFull(r, headerBuf); err != nil {
255266
return nil, err
256267
}
257268

258-
readHeaderCRC24 := uint32(header[3]) | uint32(header[4])<<8 | uint32(header[5])<<16
259-
err := sc.verifySegmentHeaderChecksum(header[:3], readHeaderCRC24)
269+
readHeaderCRC24 := uint32(headerBuf[3]) | uint32(headerBuf[4])<<8 | uint32(headerBuf[5])<<16
270+
err := sc.verifySegmentHeaderChecksum(headerBuf[:3], readHeaderCRC24)
260271
if err != nil {
261272
return nil, err
262273
}
263274

264-
headerInt := uint32(header[0]) | uint32(header[1])<<8 | uint32(header[2])<<16
275+
headerInt := uint32(headerBuf[0]) | uint32(headerBuf[1])<<8 | uint32(headerBuf[2])<<16
265276
payloadLen := int(headerInt & maxSegmentPayloadSize)
266277
isSelfContained := (headerInt & (1 << 17)) != 0
267278

@@ -278,12 +289,12 @@ func (sc *segmentCodec) decodePayload(r io.Reader, header *segmentHeader) ([]byt
278289
return nil, err
279290
}
280291

281-
var crcBuf [4]byte
282-
if _, err := io.ReadFull(r, crcBuf[:]); err != nil {
292+
crcBuf := sc.readChecksumBuf[:]
293+
if _, err := io.ReadFull(r, crcBuf); err != nil {
283294
return nil, fmt.Errorf("gocql: failed to read segment payload crc32, err: %w", err)
284295
}
285296

286-
readPayloadCRC32 := binary.LittleEndian.Uint32(crcBuf[:])
297+
readPayloadCRC32 := binary.LittleEndian.Uint32(crcBuf)
287298
err := sc.verifySegmentPayloadChecksum(payload, readPayloadCRC32)
288299
if err != nil {
289300
return nil, err

0 commit comments

Comments
 (0)