ringbuf

package module
v0.1.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 22, 2018 License: MIT Imports: 4 Imported by: 1

README

Simple ring buffer in Go

Useful for stuff like storing logs without memory going overboard, or in cases when you have multiple readers reading a single stream of data from a single writer.

This code is thread safe and allows either standard readers, or blocking readers that will wait when no more data is available (this uses sync.Cond with RLocker meaning multiple readers will resume reading in parallel, allowing the most out of goroutines).

Originally this was written as a buffer for log allowing to redirect output from logs to multiple targets at the same time (write to file and stdout at the same time) while also allowing a web API to fetch the last X MB of entries (as large as the buffer is).

Documentation

See the godoc documentation

Sample usage

	l, err := ringbuf.New(1024*1024) // 1MB ring buffer for logs
	if err != nil {
		...
	}
	log.SetOutput(l)

	// output log to stdout
	// (duplicate this to also output to files/etc)
	go func() {
		r := l.BlockingReader()
		defer r.Close()
		io.Copy(os.Stdout, r)
	}()

	func dmesg() ([]byte, error) {
		// return up to last 1MB of log entries
		r := l.Reader()
		defer r.Close()
		return ioutil.ReadAll(r)
	}

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrStaleReader = errors.New("ringbuffer reader is stale (didn't read fast enough - do you need a larger buffer?)")
)

Functions

This section is empty.

Types

type Reader

type Reader struct {
	// contains filtered or unexported fields
}

func (*Reader) Close

func (r *Reader) Close() error

Close signals this reader will not be used anymore and has finished processing, and should be called after a reader is not useful anymore.

If using Writer.Close then calling Close on readers is mandatory, failing to do so will cause a deadlock.

func (*Reader) Read

func (r *Reader) Read(p []byte) (int, error)

Read will read data from the ringbuffer to the provided buffer. If no new data is available, Read() will either return io.EOF (a later call may return new data), or block until data becomes available (if set blocking).

func (*Reader) Reset

func (r *Reader) Reset()

Reset sets the reader's position after the writer's latest write.

func (*Reader) SetAutoSkip

func (r *Reader) SetAutoSkip(enabled bool)

SetAutoSkip allows enabling auto skip, when this reader hasn't been reading fast enough and missed some data. This is generally unsafe, but in some cases may be useful to avoid having to handle stale readers.

type Writer

type Writer struct {
	// contains filtered or unexported fields
}

Ringbuf provides a object suitable for a binary stream written by one source and read by multiple consumers at the same time, provided each reader can keep up with the writes from the writer (if not, a reader will become invalid and will need to be reset)

Note: this is thread safe

func New

func New(size int64) (*Writer, error)

func (*Writer) BlockingReader

func (w *Writer) BlockingReader() *Reader

BlockingReader returns a new reader positioned at the buffer's oldest available position which reads will block if no new data is available.

func (*Writer) Close

func (w *Writer) Close() error

Close will cause all readers to return EOF once they have read the whole buffer and will wait until all readers have called Close(). If you do not need EOF synchronization you can ignore the whole close system as it is not used to free any resources, but if you use ringbuf as an output buffer, for example, it will enable waiting for writes to have completed prior to ending the program.

Note that if any reader failed to call close prior to end and being freed this will cause a deadlock.

func (*Writer) Reader

func (w *Writer) Reader() *Reader

Reader returns a new reader positioned at the buffer's oldest available position. The reader can be moved to the most recent position by calling its Reset() method.

If there isn't enough data to read, the reader's read method will return error io.EOF. If you need Read() to not return until new data is available, use BlockingReader()

func (*Writer) Size

func (w *Writer) Size() int64

func (*Writer) TotalWritten

func (w *Writer) TotalWritten() int64

func (*Writer) Write

func (w *Writer) Write(buf []byte) (int, error)

Write to buffer, will always succeed

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL