.TH "qbrb.h" 3 "Fri Apr 26 2019" "Version 1.0.5" "libqb" \" -*- nroff -*- .ad l .nh .SH NAME qbrb.h \- This implements a ring buffer that works in 'chunks', not bytes\&. .SH SYNOPSIS .br .PP \fC#include \fP .br \fC#include \fP .br .SS "Macros" .in +1c .ti -1c .RI "#define \fBQB_RB_FLAG_CREATE\fP 0x01" .br .RI "Create a ring buffer (rather than open and existing one)\&. " .ti -1c .RI "#define \fBQB_RB_FLAG_OVERWRITE\fP 0x02" .br .RI "New calls to \fBqb_rb_chunk_write()\fP will call \fBqb_rb_chunk_reclaim()\fP if there is not enough space\&. " .ti -1c .RI "#define \fBQB_RB_FLAG_SHARED_THREAD\fP 0x04" .br .RI "The ringbuffer will be shared between pthreads not processes\&. " .ti -1c .RI "#define \fBQB_RB_FLAG_SHARED_PROCESS\fP 0x08" .br .RI "The ringbuffer will be shared between processes\&. " .ti -1c .RI "#define \fBQB_RB_FLAG_NO_SEMAPHORE\fP 0x10" .br .RI "Don't use semaphores, only atomic ops\&. " .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 "Create the ring buffer with the given type\&. " .ti -1c .RI "void \fBqb_rb_close\fP (\fBqb_ringbuffer_t\fP *rb)" .br .RI "Dereference the ringbuffer and, if we are the last user, destroy it\&. " .ti -1c .RI "char * \fBqb_rb_name_get\fP (\fBqb_ringbuffer_t\fP *rb)" .br .RI "Get the name of the ringbuffer\&. " .ti -1c .RI "void * \fBqb_rb_shared_user_data_get\fP (\fBqb_ringbuffer_t\fP *rb)" .br .RI "Get a point to user shared data area\&. " .ti -1c .RI "ssize_t \fBqb_rb_chunk_write\fP (\fBqb_ringbuffer_t\fP *rb, const void *data, size_t len)" .br .RI "Write a chunk to the ring buffer\&. " .ti -1c .RI "void * \fBqb_rb_chunk_alloc\fP (\fBqb_ringbuffer_t\fP *rb, size_t len)" .br .RI "Allocate space for a chunk of the given size\&. " .ti -1c .RI "int32_t \fBqb_rb_chunk_commit\fP (\fBqb_ringbuffer_t\fP *rb, size_t len)" .br .RI "Finalize the chunk\&. " .ti -1c .RI "ssize_t \fBqb_rb_chunk_peek\fP (\fBqb_ringbuffer_t\fP *rb, void **data_out, int32_t ms_timeout)" .br .RI "Read (without reclaiming) the last chunk\&. " .ti -1c .RI "void \fBqb_rb_chunk_reclaim\fP (\fBqb_ringbuffer_t\fP *rb)" .br .RI "Reclaim the oldest chunk\&. " .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 "Read the oldest chunk into data_out\&. " .ti -1c .RI "int32_t \fBqb_rb_refcount_get\fP (\fBqb_ringbuffer_t\fP *rb)" .br .RI "Get the reference count\&. " .ti -1c .RI "ssize_t \fBqb_rb_space_free\fP (\fBqb_ringbuffer_t\fP *rb)" .br .RI "The amount of free space in the ring buffer\&. " .ti -1c .RI "ssize_t \fBqb_rb_space_used\fP (\fBqb_ringbuffer_t\fP *rb)" .br .RI "The total amount of data in the buffer\&. " .ti -1c .RI "ssize_t \fBqb_rb_chunks_used\fP (\fBqb_ringbuffer_t\fP *rb)" .br .RI "The total number of chunks in the buffer\&. " .ti -1c .RI "ssize_t \fBqb_rb_write_to_file\fP (\fBqb_ringbuffer_t\fP *rb, int32_t fd)" .br .RI "Write the contents of the Ring Buffer to file\&. " .ti -1c .RI "\fBqb_ringbuffer_t\fP * \fBqb_rb_create_from_file\fP (int32_t fd, uint32_t flags)" .br .RI "Load the saved ring buffer from file into tempory memory\&. " .ti -1c .RI "int32_t \fBqb_rb_chown\fP (\fBqb_ringbuffer_t\fP *rb, uid_t owner, gid_t group)" .br .RI "Like 'chown', it changes the owner and group of the ringbuffer's resources\&. " .ti -1c .RI "int32_t \fBqb_rb_chmod\fP (\fBqb_ringbuffer_t\fP *rb, mode_t mode)" .br .RI "Like 'chmod', it changes the mode of the ringbuffer's resources\&. " .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_t mode)" .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_t owner, gid_t group)" .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_t len)" .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_t len)" .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_t ms_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_t len, int32_t ms_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_t len)" .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_t fd, uint32_t flags)" .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_t size, uint32_t flags, size_t shared_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_t fd)" .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\&.