.TH "qbrb.h" 3 "Thu Dec 21 2017" "Version 1.0.3" "libqb" \" -*- nroff -*-
.ad l
.nh
.SH NAME
qbrb.h \-
.PP
This implements a ring buffer that works in 'chunks', not bytes\&.
.SH SYNOPSIS
.br
.PP
\fC#include <sys/types\&.h>\fP
.br
\fC#include <stdint\&.h>\fP
.br
.SS "Macros"
.in +1c
.ti -1c
.RI "#define \fBQB_RB_FLAG_CREATE\fP 0x01"
.br
.RI "\fICreate a ring buffer (rather than open and existing one)\&. \fP"
.ti -1c
.RI "#define \fBQB_RB_FLAG_OVERWRITE\fP 0x02"
.br
.RI "\fINew calls to \fBqb_rb_chunk_write()\fP will call \fBqb_rb_chunk_reclaim()\fP if there is not enough space\&. \fP"
.ti -1c
.RI "#define \fBQB_RB_FLAG_SHARED_THREAD\fP 0x04"
.br
.RI "\fIThe ringbuffer will be shared between pthreads not processes\&. \fP"
.ti -1c
.RI "#define \fBQB_RB_FLAG_SHARED_PROCESS\fP 0x08"
.br
.RI "\fIThe ringbuffer will be shared between processes\&. \fP"
.ti -1c
.RI "#define \fBQB_RB_FLAG_NO_SEMAPHORE\fP 0x10"
.br
.RI "\fIDon't use semaphores, only atomic ops\&. \fP"
.in -1c
.SS "Typedefs"
.in +1c
.ti -1c
.RI "typedef struct qb_ringbuffer_s \fBqb_ringbuffer_t\fP"
.br
.in -1c
.SS "Functions"
.in +1c
.ti -1c
.RI "\fBqb_ringbuffer_t\fP * \fBqb_rb_open\fP (const char *name, size_t size, uint32_t flags, size_t shared_user_data_size)"
.br
.RI "\fICreate the ring buffer with the given type\&. \fP"
.ti -1c
.RI "void \fBqb_rb_close\fP (\fBqb_ringbuffer_t\fP *rb)"
.br
.RI "\fIDereference the ringbuffer and, if we are the last user, destroy it\&. \fP"
.ti -1c
.RI "char * \fBqb_rb_name_get\fP (\fBqb_ringbuffer_t\fP *rb)"
.br
.RI "\fIGet the name of the ringbuffer\&. \fP"
.ti -1c
.RI "void * \fBqb_rb_shared_user_data_get\fP (\fBqb_ringbuffer_t\fP *rb)"
.br
.RI "\fIGet a point to user shared data area\&. \fP"
.ti -1c
.RI "ssize_t \fBqb_rb_chunk_write\fP (\fBqb_ringbuffer_t\fP *rb, const void *data, size_t len)"
.br
.RI "\fIWrite a chunk to the ring buffer\&. \fP"
.ti -1c
.RI "void * \fBqb_rb_chunk_alloc\fP (\fBqb_ringbuffer_t\fP *rb, size_t len)"
.br
.RI "\fIAllocate space for a chunk of the given size\&. \fP"
.ti -1c
.RI "int32_t \fBqb_rb_chunk_commit\fP (\fBqb_ringbuffer_t\fP *rb, size_t len)"
.br
.RI "\fIFinalize the chunk\&. \fP"
.ti -1c
.RI "ssize_t \fBqb_rb_chunk_peek\fP (\fBqb_ringbuffer_t\fP *rb, void **data_out, int32_t ms_timeout)"
.br
.RI "\fIRead (without reclaiming) the last chunk\&. \fP"
.ti -1c
.RI "void \fBqb_rb_chunk_reclaim\fP (\fBqb_ringbuffer_t\fP *rb)"
.br
.RI "\fIReclaim the oldest chunk\&. \fP"
.ti -1c
.RI "ssize_t \fBqb_rb_chunk_read\fP (\fBqb_ringbuffer_t\fP *rb, void *data_out, size_t len, int32_t ms_timeout)"
.br
.RI "\fIRead the oldest chunk into data_out\&. \fP"
.ti -1c
.RI "int32_t \fBqb_rb_refcount_get\fP (\fBqb_ringbuffer_t\fP *rb)"
.br
.RI "\fIGet the reference count\&. \fP"
.ti -1c
.RI "ssize_t \fBqb_rb_space_free\fP (\fBqb_ringbuffer_t\fP *rb)"
.br
.RI "\fIThe amount of free space in the ring buffer\&. \fP"
.ti -1c
.RI "ssize_t \fBqb_rb_space_used\fP (\fBqb_ringbuffer_t\fP *rb)"
.br
.RI "\fIThe total amount of data in the buffer\&. \fP"
.ti -1c
.RI "ssize_t \fBqb_rb_chunks_used\fP (\fBqb_ringbuffer_t\fP *rb)"
.br
.RI "\fIThe total number of chunks in the buffer\&. \fP"
.ti -1c
.RI "ssize_t \fBqb_rb_write_to_file\fP (\fBqb_ringbuffer_t\fP *rb, int32_t fd)"
.br
.RI "\fIWrite the contents of the Ring Buffer to file\&. \fP"
.ti -1c
.RI "\fBqb_ringbuffer_t\fP * \fBqb_rb_create_from_file\fP (int32_t fd, uint32_t flags)"
.br
.RI "\fILoad the saved ring buffer from file into tempory memory\&. \fP"
.ti -1c
.RI "int32_t \fBqb_rb_chown\fP (\fBqb_ringbuffer_t\fP *rb, uid_t owner, gid_t group)"
.br
.RI "\fILike 'chown', it changes the owner and group of the ringbuffer's resources\&. \fP"
.ti -1c
.RI "int32_t \fBqb_rb_chmod\fP (\fBqb_ringbuffer_t\fP *rb, mode_t mode)"
.br
.RI "\fILike 'chmod', it changes the mode of the ringbuffer's resources\&. \fP"
.in -1c
.SH "Detailed Description"
.PP
This implements a ring buffer that works in 'chunks', not bytes\&.
So you write/read a complete chunk or not at all\&. There are two types of ring buffer: normal and overwrite\&. Overwrite will reclaim the oldest chunks inorder to make way for new ones, the normal version will refuse to write a new chunk if the ring buffer is full\&.
.PP
This implementation is capable of working across processes, but one process must only write and the other process read\&.
.PP
The read process will do the following:
.PP
.nf
* rb = qb_rb_open("test2", 2000, QB_RB_FLAG_SHARED_PROCESS|QB_RB_FLAG_CREATE);
* for (i = 0; i < 200; i++) {
* try_read_again:
* l = qb_rb_chunk_read(rb, (void *)out, 32, 1000);
* if (l < 0) {
* goto try_read_again;
* }
* }
* \&.\&.\&.
* qb_rb_close(rb);
*
*
.fi
.PP
.PP
The write process will do the following:
.PP
.nf
* rb = qb_rb_open("test2", 2000, QB_RB_FLAG_SHARED_PROCESS);
* for (i = 0; i < 200; i++) {
* try_write_again:
* l = qb_rb_chunk_write(rb, &v, sizeof(v));
* if (l < sizeof(v)) {
* goto try_write_again;
* }
* }
* \&.\&.\&.
* qb_rb_close(rb);
*
.fi
.PP
.PP
\fBAuthor:\fP
.RS 4
Angus Salkeld asalkeld@redhat.com
.RE
.PP
.SH "Macro Definition Documentation"
.PP
.SS "#define QB_RB_FLAG_CREATE 0x01"
.PP
Create a ring buffer (rather than open and existing one)\&.
.PP
\fBSee Also:\fP
.RS 4
\fBqb_rb_open()\fP
.RE
.PP
.SS "#define QB_RB_FLAG_NO_SEMAPHORE 0x10"
.PP
Don't use semaphores, only atomic ops\&. This mean that the timeout passed into \fBqb_rb_chunk_read()\fP will be ignored\&.
.SS "#define QB_RB_FLAG_OVERWRITE 0x02"
.PP
New calls to \fBqb_rb_chunk_write()\fP will call \fBqb_rb_chunk_reclaim()\fP if there is not enough space\&. If this is not set then new writes will be refused\&.
.PP
\fBSee Also:\fP
.RS 4
\fBqb_rb_open()\fP
.RE
.PP
.SS "#define QB_RB_FLAG_SHARED_PROCESS 0x08"
.PP
The ringbuffer will be shared between processes\&. This effects the type of locks/semaphores that are used\&.
.PP
\fBSee Also:\fP
.RS 4
\fBqb_rb_open()\fP
.RE
.PP
.SS "#define QB_RB_FLAG_SHARED_THREAD 0x04"
.PP
The ringbuffer will be shared between pthreads not processes\&. This effects the type of locks/semaphores that are used\&.
.PP
\fBSee Also:\fP
.RS 4
\fBqb_rb_open()\fP
.RE
.PP
.SH "Typedef Documentation"
.PP
.SS "typedef struct qb_ringbuffer_s \fBqb_ringbuffer_t\fP"
.SH "Function Documentation"
.PP
.SS "int32_t qb_rb_chmod (\fBqb_ringbuffer_t\fP *rb, mode_tmode)"
.PP
Like 'chmod', it changes the mode of the ringbuffer's resources\&.
.PP
\fBParameters:\fP
.RS 4
\fImode\fP mode to change to
.br
\fIrb\fP ringbuffer instance
.RE
.PP
\fBReturn values:\fP
.RS 4
\fI0\fP == ok
.br
\fI-errno\fP for error
.RE
.PP
.SS "int32_t qb_rb_chown (\fBqb_ringbuffer_t\fP *rb, uid_towner, gid_tgroup)"
.PP
Like 'chown', it changes the owner and group of the ringbuffer's resources\&.
.PP
\fBParameters:\fP
.RS 4
\fIowner\fP uid of the owner to change to
.br
\fIgroup\fP gid of the group to change to
.br
\fIrb\fP ringbuffer instance
.RE
.PP
\fBReturns:\fP
.RS 4
status (0 = ok, -errno for error)
.RE
.PP
.SS "void* qb_rb_chunk_alloc (\fBqb_ringbuffer_t\fP *rb, size_tlen)"
.PP
Allocate space for a chunk of the given size\&. If type == QB_RB_FLAG_OVERWRITE and NULL is returned, memory corruption of the memory file has occurred\&. The ringbuffer should be destroyed\&. If type == QB_RB_NORMAL then when there is not enough space it will return NULL\&.
.PP
\fBParameters:\fP
.RS 4
\fIrb\fP ringbuffer instance
.br
\fIlen\fP (in) the size to allocate\&.
.RE
.PP
\fBReturns:\fP
.RS 4
pointer to chunk to write to, or NULL (if no space)\&.
.RE
.PP
\fBSee Also:\fP
.RS 4
\fBqb_rb_chunk_alloc()\fP
.RE
.PP
.SS "int32_t qb_rb_chunk_commit (\fBqb_ringbuffer_t\fP *rb, size_tlen)"
.PP
Finalize the chunk\&.
.PP
\fBParameters:\fP
.RS 4
\fIrb\fP ringbuffer instance
.br
\fIlen\fP (in) the size of the chunk\&.
.RE
.PP
.SS "ssize_t qb_rb_chunk_peek (\fBqb_ringbuffer_t\fP *rb, void **data_out, int32_tms_timeout)"
.PP
Read (without reclaiming) the last chunk\&. This function is a way of accessing the next chunk without a memcpy()\&. You can read the chunk data in place\&.
.PP
\fBNote:\fP
.RS 4
This function will not 'pop' the chunk, you will need to call \fBqb_rb_chunk_reclaim()\fP\&.
.RE
.PP
\fBParameters:\fP
.RS 4
\fIrb\fP ringbuffer instance
.br
\fIdata_out\fP (out) a pointer to the next chunk to read (not copied)\&.
.br
\fIms_timeout\fP (in) time to wait for new data\&.
.RE
.PP
\fBReturns:\fP
.RS 4
the size of the chunk (0 if buffer empty)\&.
.RE
.PP
.SS "ssize_t qb_rb_chunk_read (\fBqb_ringbuffer_t\fP *rb, void *data_out, size_tlen, int32_tms_timeout)"
.PP
Read the oldest chunk into data_out\&. This is the same as \fBqb_rb_chunk_peek()\fP memcpy() and \fBqb_rb_chunk_reclaim()\fP\&.
.PP
\fBParameters:\fP
.RS 4
\fIrb\fP ringbuffer instance
.br
\fIdata_out\fP (in/out) the chunk will be memcpy'ed into this\&.
.br
\fIlen\fP (in) the size of data_out\&.
.br
\fIms_timeout\fP the amount od time to wait for new data\&.
.RE
.PP
\fBReturns:\fP
.RS 4
the size of the chunk, or error\&.
.RE
.PP
.SS "void qb_rb_chunk_reclaim (\fBqb_ringbuffer_t\fP *rb)"
.PP
Reclaim the oldest chunk\&. You will need to call this if using \fBqb_rb_chunk_peek()\fP\&.
.PP
\fBParameters:\fP
.RS 4
\fIrb\fP ringbuffer instance
.RE
.PP
.SS "ssize_t qb_rb_chunk_write (\fBqb_ringbuffer_t\fP *rb, const void *data, size_tlen)"
.PP
Write a chunk to the ring buffer\&. This simply calls \fBqb_rb_chunk_alloc()\fP and then \fBqb_rb_chunk_commit()\fP\&.
.PP
\fBParameters:\fP
.RS 4
\fIrb\fP ringbuffer instance
.br
\fIdata\fP (in) the data to write
.br
\fIlen\fP (in) the size of the chunk\&.
.RE
.PP
\fBReturns:\fP
.RS 4
the amount of bytes actually buffered (either len or -1)\&.
.RE
.PP
\fBSee Also:\fP
.RS 4
\fBqb_rb_chunk_alloc()\fP
.PP
\fBqb_rb_chunk_commit()\fP
.RE
.PP
.SS "ssize_t qb_rb_chunks_used (\fBqb_ringbuffer_t\fP *rb)"
.PP
The total number of chunks in the buffer\&.
.PP
\fBParameters:\fP
.RS 4
\fIrb\fP ringbuffer instance
.RE
.PP
.SS "void qb_rb_close (\fBqb_ringbuffer_t\fP *rb)"
.PP
Dereference the ringbuffer and, if we are the last user, destroy it\&. All files, mmaped memory, semaphores and locks will be destroyed\&.
.PP
\fBParameters:\fP
.RS 4
\fIrb\fP ringbuffer instance
.RE
.PP
.SS "\fBqb_ringbuffer_t\fP* qb_rb_create_from_file (int32_tfd, uint32_tflags)"
.PP
Load the saved ring buffer from file into tempory memory\&.
.PP
\fBParameters:\fP
.RS 4
\fIfd\fP file with saved ringbuffer data\&.
.br
\fIflags\fP same flags as passed into \fBqb_rb_open()\fP
.RE
.PP
\fBReturns:\fP
.RS 4
new ringbuffer instance
.RE
.PP
\fBSee Also:\fP
.RS 4
\fBqb_rb_write_to_file()\fP
.RE
.PP
.SS "char* qb_rb_name_get (\fBqb_ringbuffer_t\fP *rb)"
.PP
Get the name of the ringbuffer\&.
.PP
\fBParameters:\fP
.RS 4
\fIrb\fP ringbuffer instance
.RE
.PP
\fBReturns:\fP
.RS 4
name\&.
.RE
.PP
.SS "\fBqb_ringbuffer_t\fP* qb_rb_open (const char *name, size_tsize, uint32_tflags, size_tshared_user_data_size)"
.PP
Create the ring buffer with the given type\&. This creates allocates a ring buffer in shared memory\&.
.PP
\fBParameters:\fP
.RS 4
\fIname\fP the unique name of this ringbuffer\&.
.br
\fIsize\fP the requested size\&.
.br
\fIflags\fP or'ed flags
.br
\fIshared_user_data_size\fP size for a shared data area\&.
.RE
.PP
\fBNote:\fP
.RS 4
the actual size will be rounded up to the next page size\&.
.RE
.PP
\fBReturns:\fP
.RS 4
a new ring buffer or NULL if there was a problem\&.
.RE
.PP
\fBSee Also:\fP
.RS 4
\fBQB_RB_FLAG_CREATE\fP, \fBQB_RB_FLAG_OVERWRITE\fP, \fBQB_RB_FLAG_SHARED_THREAD\fP, \fBQB_RB_FLAG_SHARED_PROCESS\fP
.RE
.PP
.SS "int32_t qb_rb_refcount_get (\fBqb_ringbuffer_t\fP *rb)"
.PP
Get the reference count\&.
.PP
\fBParameters:\fP
.RS 4
\fIrb\fP ringbuffer instance
.RE
.PP
\fBReturns:\fP
.RS 4
the number of references
.RE
.PP
.SS "void* qb_rb_shared_user_data_get (\fBqb_ringbuffer_t\fP *rb)"
.PP
Get a point to user shared data area\&.
.PP
\fBNote:\fP
.RS 4
this is of size 'shared_user_data_size' passed into \fBqb_rb_open()\fP
.RE
.PP
\fBParameters:\fP
.RS 4
\fIrb\fP ringbuffer instance
.RE
.PP
\fBReturns:\fP
.RS 4
pointer to shared data\&.
.RE
.PP
.SS "ssize_t qb_rb_space_free (\fBqb_ringbuffer_t\fP *rb)"
.PP
The amount of free space in the ring buffer\&.
.PP
\fBNote:\fP
.RS 4
Some of this space will be consumed by the chunk headers\&.
.RE
.PP
\fBParameters:\fP
.RS 4
\fIrb\fP ringbuffer instance
.RE
.PP
.SS "ssize_t qb_rb_space_used (\fBqb_ringbuffer_t\fP *rb)"
.PP
The total amount of data in the buffer\&.
.PP
\fBNote:\fP
.RS 4
This includes the chunk headers (8 bytes per chunk)\&.
.RE
.PP
\fBParameters:\fP
.RS 4
\fIrb\fP ringbuffer instance
.RE
.PP
.SS "ssize_t qb_rb_write_to_file (\fBqb_ringbuffer_t\fP *rb, int32_tfd)"
.PP
Write the contents of the Ring Buffer to file\&.
.PP
\fBParameters:\fP
.RS 4
\fIfd\fP open file to write the ringbuffer data to\&.
.br
\fIrb\fP ringbuffer instance
.RE
.PP
\fBSee Also:\fP
.RS 4
\fBqb_rb_create_from_file()\fP
.RE
.PP
.SH "Author"
.PP
Generated automatically by Doxygen for libqb from the source code\&.