Skip to content

Commit

Permalink
Simplify writer by relying on the io.Writer for everything.
Browse files Browse the repository at this point in the history
  • Loading branch information
davidlion committed Oct 31, 2024
1 parent 55e28ac commit 850d0ff
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 65 deletions.
2 changes: 2 additions & 0 deletions ir/ir.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,5 @@ type LogMessage[T EightByteEncoding | FourByteEncoding] struct {
type LogMessageView[T EightByteEncoding | FourByteEncoding] struct {
LogMessage[T]
}

const FfiSuccess = 0
13 changes: 7 additions & 6 deletions ir/serializer.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package ir
import "C"

import (
"syscall"
"unsafe"

"github.com/y-scope/clp-ffi-go/ffi"
Expand Down Expand Up @@ -38,7 +39,7 @@ func EightByteSerializer() (Serializer, BufView, error) {
if err := IrError(C.ir_serializer_eight_byte_create(
&irs.cptr,
&irView,
)); Success != err {
)); FfiSuccess != err {
return nil, nil, err
}
return &irs, unsafe.Slice((*byte)(irView.m_data), irView.m_size), nil
Expand All @@ -56,7 +57,7 @@ func FourByteSerializer() (Serializer, BufView, error) {
if err := IrError(C.ir_serializer_four_byte_create(
&irs.cptr,
&irView,
)); Success != err {
)); FfiSuccess != err {
return nil, nil, err
}
return &irs, unsafe.Slice((*byte)(irView.m_data), irView.m_size), nil
Expand Down Expand Up @@ -158,23 +159,23 @@ func serializeMsgPackBytes(
msgPackBytes []byte,
) (BufView, error) {
var irView C.ByteSpan
var err error
var err syscall.Errno

switch irs := serializer.(type) {
case *eightByteSerializer:
err = IrError(C.ir_serializer_eight_byte_serialize_log_event(
err = syscall.Errno(C.ir_serializer_eight_byte_serialize_log_event(
irs.cptr,
newCByteSpan(msgPackBytes),
&irView,
))
case *fourByteSerializer:
err = IrError(C.ir_serializer_four_byte_serialize_log_event(
err = syscall.Errno(C.ir_serializer_four_byte_serialize_log_event(
irs.cptr,
newCByteSpan(msgPackBytes),
&irView,
))
}
if Success != err {
if FfiSuccess != err {
return nil, err
}
return unsafe.Slice((*byte)(irView.m_data), irView.m_size), nil
Expand Down
64 changes: 10 additions & 54 deletions ir/writer.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package ir

import (
"bytes"
"fmt"
"io"

Expand All @@ -13,31 +12,23 @@ import (
// the arguments used. Close must be called to free the underlying memory and
// failure to do so will result in a memory leak. To write a complete IR stream
// Close must be called before the final WriteTo call.
// buffer in ioWriter if necessary
type Writer struct {
Serializer
buf bytes.Buffer
ioWriter io.Writer
}

// Returns [NewWriterSize] with a FourByteEncoding Serializer using a buffer size of 1MB.
func NewWriter(ioWriter io.Writer) (*Writer, error) {
return NewWriterSize[FourByteEncoding](ioWriter, 1024*1024)
}

// NewWriterSize creates a new [Writer] with a [Serializer] based on T, and
// writes a CLP IR preamble. The preamble is stored inside the Writer's internal
// buffer to be written out later. The size parameter denotes the initial buffer
// size to use.
// - success: valid [*Writer], nil
// - error: nil [*Writer], invalid type error or an error propagated from
// [FourByteSerializer], [EightByteSerializer], or [bytes.Buffer.Write]
func NewWriterSize[T EightByteEncoding | FourByteEncoding](
func NewWriter[T EightByteEncoding | FourByteEncoding](
ioWriter io.Writer,
size int,
) (*Writer, error) {
var irw Writer
irw.buf.Grow(size)

var irView BufView
var err error
var t T
Expand All @@ -52,45 +43,25 @@ func NewWriterSize[T EightByteEncoding | FourByteEncoding](
if nil != err {
return nil, err
}
_, err = irw.buf.Write(irView)
_, err = ioWriter.Write(irView)
if nil != err {
return nil, err
}
irw.ioWriter = ioWriter
return &irw, nil
}

// Close will write a null byte denoting the end of the IR stream and delete the
// underlying C++ allocated memory used by the serializer. Failure to call Close
// will result in a memory leak.
func (writer *Writer) Close() error {
writer.buf.WriteByte(0x0)
_, err := writer.ioWriter.Write([]byte{0x0})
if nil != err {
return err
}
return writer.Serializer.Close()
}

// CloseTo is a combination of [Close] and [WriteTo]. It will completely close
// the Writer (and underlying serializer) and write the data out to the
// io.Writer.
// Returns:
// - success: number of bytes written, nil
// - error: number of bytes written, error propagated from [WriteTo]
func (writer *Writer) CloseTo(w io.Writer) (int64, error) {
writer.Close()
return writer.WriteTo(w)
}

// Bytes returns a slice of the Writer's internal buffer. The slice is valid for
// use only until the next buffer modification (that is, only until the next
// call to Write, WriteTo, or Reset).
func (writer *Writer) Bytes() []byte {
return writer.buf.Bytes()
}

// Reset resets the buffer to be empty, but it retains the underlying storage
// for use by future writes.
func (writer *Writer) Reset() {
writer.buf.Reset()
}

// Write uses [SerializeLogEvent] to serialize the provided log event to CLP IR
// and then stores it in the internal buffer. Returns:
// - success: number of bytes written, nil
Expand All @@ -106,7 +77,7 @@ func (writer *Writer) WriteLogEvent(logEvent ffi.LogEvent) (int, error) {
// Write can fail in the future, we should either:
// 1. fix the issue and retry the write
// 2. store irView and provide a retry API (allowing the user to fix the issue and retry)
n, err := writer.buf.Write(irView)
n, err := writer.ioWriter.Write(irView)
if nil != err {
return n, err
}
Expand All @@ -128,24 +99,9 @@ func (writer *Writer) WriteMsgPackBytes(msgPackBytes []byte) (int, error) {
// Write can fail in the future, we should either:
// 1. fix the issue and retry the write
// 2. store irView and provide a retry API (allowing the user to fix the issue and retry)
n, err := writer.buf.Write(irView)
n, err := writer.ioWriter.Write(irView)
if nil != err {
return n, err
}
return n, nil
}

// WriteTo writes data to w until the buffer is drained or an error occurs. If
// no error occurs the buffer is reset. On an error the user is expected to use
// [writer.Bytes] and [writer.Reset] to manually handle the buffer's contents before
// continuing. Returns:
// - success: number of bytes written, nil
// - error: number of bytes written, error propagated from
// [bytes.Buffer.WriteTo]
func (writer *Writer) WriteTo(w io.Writer) (int64, error) {
n, err := writer.buf.WriteTo(w)
if nil == err {
writer.buf.Reset()
}
return n, err
}
10 changes: 5 additions & 5 deletions ir/writeread_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ func testWriteReadLogMessages(
}
events = append(events, event)
}
_, err := irWriter.CloseTo(ioWriter)
err := irWriter.Close()
if nil != err {
t.Fatalf("ir.Writer.CloseTo failed: %v", err)
t.Fatalf("ir.Writer.Close failed: %v", err)
}
ioWriter.Close()

Expand All @@ -57,14 +57,14 @@ func openIrWriter(
var err error
switch args.encoding {
case eightByteEncoding:
irWriter, err = NewWriterSize[EightByteEncoding](writer, 1024*1024)
irWriter, err = NewWriter[EightByteEncoding](writer)
case fourByteEncoding:
irWriter, err = NewWriterSize[FourByteEncoding](writer, 1024*1024)
irWriter, err = NewWriter[FourByteEncoding](writer)
default:
t.Fatalf("unsupported encoding: %v", args.encoding)
}
if nil != err {
t.Fatalf("NewWriterSize failed: %v", err)
t.Fatalf("NewWriter failed: %v", err)
}
return irWriter
}

0 comments on commit 850d0ff

Please sign in to comment.