libisofs  1.5.4
About: libisofs is a library to create an ISO 9660 filesystem, supports extensions like RockRidge or Joliet, makes bootable ISO 9660, and records file attributes which are of interest for data backups.
  Fossies Dox: libisofs-1.5.4.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

buffer.c File Reference
#include "libisofs.h"
#include "buffer.h"
#include "ecma119.h"
#include <pthread.h>
#include <string.h>
Include dependency graph for buffer.c:

Go to the source code of this file.

Data Structures

struct  iso_ring_buffer
 

Macros

#define LIBISOFS_WITHOUT_LIBBURN   yes
 

Functions

int iso_ring_buffer_new (size_t size, IsoRingBuffer **rbuf)
 Create a new buffer. More...
 
void iso_ring_buffer_free (IsoRingBuffer *buf)
 Free a given buffer. More...
 
int iso_ring_buffer_write (IsoRingBuffer *buf, uint8_t *data, size_t count)
 Write count bytes into buffer. More...
 
int iso_ring_buffer_read (IsoRingBuffer *buf, uint8_t *dest, size_t count)
 Read count bytes from the buffer into dest. More...
 
void iso_ring_buffer_writer_close (IsoRingBuffer *buf, int error)
 Close the buffer (to be called by the writer). More...
 
void iso_ring_buffer_reader_close (IsoRingBuffer *buf, int error)
 Close the buffer (to be called by the reader). More...
 
unsigned int iso_ring_buffer_get_times_full (IsoRingBuffer *buf)
 Get the times the buffer was full. More...
 
unsigned int iso_ring_buffer_get_times_empty (IsoRingBuffer *buf)
 Get the times the buffer was empty. More...
 
int iso_ring_buffer_get_buf_status (IsoRingBuffer *buf, size_t *size, size_t *free_bytes)
 Internal via buffer.h. More...
 
int iso_ring_buffer_get_status (struct burn_source *b, size_t *size, size_t *free_bytes)
 API via libisofs.h. More...
 

Macro Definition Documentation

◆ LIBISOFS_WITHOUT_LIBBURN

#define LIBISOFS_WITHOUT_LIBBURN   yes

Definition at line 27 of file buffer.c.

Function Documentation

◆ iso_ring_buffer_free()

void iso_ring_buffer_free ( IsoRingBuffer buf)

Free a given buffer.

Definition at line 124 of file buffer.c.

125 {
126  if (buf == NULL) {
127  return;
128  }
129  free(buf->buf);
130  pthread_mutex_destroy(&buf->mutex);
131  pthread_cond_destroy(&buf->empty);
132  pthread_cond_destroy(&buf->full);
133  free(buf);
134 }
pthread_mutex_t mutex
Definition: buffer.c:69
pthread_cond_t full
Definition: buffer.c:71
pthread_cond_t empty
Definition: buffer.c:70
uint8_t * buf
Definition: buffer.c:42

References iso_ring_buffer::buf, iso_ring_buffer::empty, iso_ring_buffer::full, and iso_ring_buffer::mutex.

Referenced by ecma119_image_free().

◆ iso_ring_buffer_get_buf_status()

int iso_ring_buffer_get_buf_status ( IsoRingBuffer buf,
size_t *  size,
size_t *  free_bytes 
)

Internal via buffer.h.

Backend of API call iso_ring_buffer_get_status()

Get the status of a ring buffer.

Parameters
bufThe ring buffer object to inquire
sizeWill be filled with the total size of the buffer, in bytes
free_bytesWill be filled with the bytes currently available in buffer
Returns
< 0 error, > 0 state: 1="active" : input and consumption are active 2="ending" : input has ended without error 3="failing" : input had error and ended, 5="abandoned" : consumption has ended prematurely 6="ended" : consumption has ended without input error 7="aborted" : consumption has ended after input error

Definition at line 315 of file buffer.c.

317 {
318  int ret;
319 
320  if (buf == NULL) {
321  return ISO_NULL_POINTER;
322  }
323 
324  /* get mutex */
325  pthread_mutex_lock(&buf->mutex);
326  if (size) {
327  *size = buf->cap;
328  }
329  if (free_bytes) {
330  *free_bytes = buf->cap - buf->size;
331  }
332 
333  ret = (buf->rend ? 4 : 0) + (buf->wend + 1);
334 
335  pthread_mutex_unlock(&buf->mutex);
336  return ret;
337 }
#define ISO_NULL_POINTER
NULL pointer as value for an arg.
Definition: libisofs.h:8742
unsigned int wend
Definition: buffer.c:63
size_t cap
Definition: buffer.c:47
unsigned int rend
Definition: buffer.c:62
size_t size
Definition: buffer.c:52

References iso_ring_buffer::cap, ISO_NULL_POINTER, iso_ring_buffer::mutex, iso_ring_buffer::rend, iso_ring_buffer::size, and iso_ring_buffer::wend.

Referenced by iso_ring_buffer_get_status(), and write_head_part1().

◆ iso_ring_buffer_get_status()

int iso_ring_buffer_get_status ( struct burn_source *  b,
size_t *  size,
size_t *  free_bytes 
)

API via libisofs.h.

Get the status of the buffer used by a burn_source.

Get the status of the buffer used by a burn_source.

Parameters
bA burn_source previously obtained with iso_image_create_burn_source().
sizeWill be filled with the total size of the buffer, in bytes
free_bytesWill be filled with the bytes currently available in buffer
Returns
< 0 error, > 0 state: 1="active" : input and consumption are active 2="ending" : input has ended without error 3="failing" : input had error and ended, 5="abandoned" : consumption has ended prematurely 6="ended" : consumption has ended without input error 7="aborted" : consumption has ended after input error

Definition at line 359 of file buffer.c.

361 {
362  int ret;
363  IsoRingBuffer *buf;
364  if (b == NULL) {
365  return ISO_NULL_POINTER;
366  }
367  buf = ((Ecma119Image*)(b->data))->buffer;
368  ret = iso_ring_buffer_get_buf_status(buf, size, free_bytes);
369  return ret;
370 }
int iso_ring_buffer_get_buf_status(IsoRingBuffer *buf, size_t *size, size_t *free_bytes)
Internal via buffer.h.
Definition: buffer.c:315

References ISO_NULL_POINTER, and iso_ring_buffer_get_buf_status().

Referenced by bs_cancel(), and bs_free_data().

◆ iso_ring_buffer_get_times_empty()

unsigned int iso_ring_buffer_get_times_empty ( IsoRingBuffer buf)

Get the times the buffer was empty.

Definition at line 290 of file buffer.c.

291 {
292  return buf->times_empty;
293 }
unsigned int times_empty
Definition: buffer.c:67

References iso_ring_buffer::times_empty.

Referenced by bs_free_data().

◆ iso_ring_buffer_get_times_full()

unsigned int iso_ring_buffer_get_times_full ( IsoRingBuffer buf)

Get the times the buffer was full.

Definition at line 282 of file buffer.c.

283 {
284  return buf->times_full;
285 }
unsigned int times_full
Definition: buffer.c:66

References iso_ring_buffer::times_full.

Referenced by bs_free_data().

◆ iso_ring_buffer_new()

int iso_ring_buffer_new ( size_t  size,
IsoRingBuffer **  rbuf 
)

Create a new buffer.

The created buffer should be freed with iso_ring_buffer_free()

Parameters
sizeNumber of blocks in buffer. You should supply a number >= 32, otherwise size will be ignored and 32 will be used by default, which leads to a 64 KiB buffer.
Returns
1 success, < 0 error

Definition at line 86 of file buffer.c.

87 {
88  IsoRingBuffer *buffer;
89 
90  if (rbuf == NULL) {
91  return ISO_NULL_POINTER;
92  }
93 
94  buffer = malloc(sizeof(IsoRingBuffer));
95  if (buffer == NULL) {
96  return ISO_OUT_OF_MEM;
97  }
98 
99  buffer->cap = (size > 32 ? size : 32) * BLOCK_SIZE;
100  buffer->buf = malloc(buffer->cap);
101  if (buffer->buf == NULL) {
102  free(buffer);
103  return ISO_OUT_OF_MEM;
104  }
105 
106  buffer->size = 0;
107  buffer->wpos = 0;
108  buffer->rpos = 0;
109 
110  buffer->times_full = 0;
111  buffer->times_empty = 0;
112 
113  buffer->rend = buffer->wend = 0;
114 
115  /* init mutex and waiting queues */
116  pthread_mutex_init(&buffer->mutex, NULL);
117  pthread_cond_init(&buffer->empty, NULL);
118  pthread_cond_init(&buffer->full, NULL);
119 
120  *rbuf = buffer;
121  return ISO_SUCCESS;
122 }
#define BLOCK_SIZE
Definition: buffer.h:23
#define ISO_SUCCESS
successfully execution
Definition: libisofs.h:8719
#define ISO_OUT_OF_MEM
Memory allocation error (FATAL,HIGH, -6)
Definition: libisofs.h:8745
size_t rpos
Definition: buffer.c:55
size_t wpos
Definition: buffer.c:56

References BLOCK_SIZE, iso_ring_buffer::buf, iso_ring_buffer::cap, iso_ring_buffer::empty, iso_ring_buffer::full, ISO_NULL_POINTER, ISO_OUT_OF_MEM, ISO_SUCCESS, iso_ring_buffer::mutex, iso_ring_buffer::rend, iso_ring_buffer::rpos, iso_ring_buffer::size, iso_ring_buffer::times_empty, iso_ring_buffer::times_full, iso_ring_buffer::wend, and iso_ring_buffer::wpos.

Referenced by ecma119_image_new().

◆ iso_ring_buffer_read()

int iso_ring_buffer_read ( IsoRingBuffer buf,
uint8_t *  dest,
size_t  count 
)

Read count bytes from the buffer into dest.

It blocks until the desired bytes has been read. If the writer finishes before outputting enough bytes, 0 (EOF) is returned, the number of bytes already read remains unknown.

Returns
1 success, 0 EOF, < 0 error

Definition at line 206 of file buffer.c.

207 {
208  size_t len;
209  size_t bytes_read = 0;
210 
211  if (buf == NULL || dest == NULL) {
212  return ISO_NULL_POINTER;
213  }
214 
215  while (bytes_read < count) {
216  pthread_mutex_lock(&buf->mutex);
217 
218  while (buf->size == 0) {
219  /*
220  * Note. There's only a reader, so we have no race conditions.
221  * Thus, the while(buf->size == 0) is used here just to ensure
222  * a reader detects the EOF properly if the writer has been
223  * canceled while the reader was waiting
224  */
225 
226  if (buf->wend) {
227  /* the writer procces has been finished */
228  pthread_mutex_unlock(&buf->mutex);
229  return 0; /* EOF */
230  }
231  buf->times_empty++;
232  /* wait until data available */
233  pthread_cond_wait(&buf->empty, &buf->mutex);
234  }
235 
236  len = MIN(count - bytes_read, buf->size);
237  if (buf->rpos + len > buf->cap) {
238  len = buf->cap - buf->rpos;
239  }
240  memcpy(dest + bytes_read, buf->buf + buf->rpos, len);
241  buf->rpos = (buf->rpos + len) % (buf->cap);
242  bytes_read += len;
243  buf->size -= len;
244 
245  /* wake up the writer */
246  pthread_cond_signal(&buf->full);
247  pthread_mutex_unlock(&buf->mutex);
248  }
249  return ISO_SUCCESS;
250 }
#define MIN(a, b)
Definition: util.h:35

References iso_ring_buffer::buf, iso_ring_buffer::cap, iso_ring_buffer::empty, iso_ring_buffer::full, ISO_NULL_POINTER, ISO_SUCCESS, MIN, iso_ring_buffer::mutex, iso_ring_buffer::rpos, iso_ring_buffer::size, iso_ring_buffer::times_empty, and iso_ring_buffer::wend.

Referenced by bs_read(), and ecma119_image_new().

◆ iso_ring_buffer_reader_close()

void iso_ring_buffer_reader_close ( IsoRingBuffer buf,
int  error 
)

Close the buffer (to be called by the reader).

If for any reason you don't want to read more data, you need to call this to let the writer thread finish.

Parameters
errorReader has finished prematurely due to an error

Definition at line 262 of file buffer.c.

263 {
264  pthread_mutex_lock(&buf->mutex);
265 
266  if (buf->rend) {
267  /* reader already closed */
268  pthread_mutex_unlock(&buf->mutex);
269  return;
270  }
271 
272  buf->rend = error ? 2 : 1;
273 
274  /* ensure no writer is waiting */
275  pthread_cond_signal(&buf->full);
276  pthread_mutex_unlock(&buf->mutex);
277 }

References iso_ring_buffer::full, iso_ring_buffer::mutex, and iso_ring_buffer::rend.

Referenced by bs_cancel(), and bs_free_data().

◆ iso_ring_buffer_write()

int iso_ring_buffer_write ( IsoRingBuffer buf,
uint8_t *  data,
size_t  count 
)

Write count bytes into buffer.

It blocks until all bytes where written or reader close the buffer.

Parameters
bufthe buffer
datapointer to a memory region of at least coun bytes, from which data will be read.
Numberof bytes to write
Returns
1 success, 0 read finished, < 0 error

Definition at line 150 of file buffer.c.

151 {
152  size_t len;
153  size_t bytes_write = 0;
154 
155  if (buf == NULL || data == NULL) {
156  return ISO_NULL_POINTER;
157  }
158 
159  while (bytes_write < count) {
160 
161  pthread_mutex_lock(&buf->mutex);
162 
163  while (buf->size == buf->cap) {
164 
165  /*
166  * Note. There's only a writer, so we have no race conditions.
167  * Thus, the while(buf->size == buf->cap) is used here
168  * only to properly detect the reader has been cancelled
169  */
170 
171  if (buf->rend) {
172  /* the read procces has been finished */
173  pthread_mutex_unlock(&buf->mutex);
174  return 0;
175  }
176  buf->times_full++;
177  /* wait until space available */
178  pthread_cond_wait(&buf->full, &buf->mutex);
179  }
180 
181  len = MIN(count - bytes_write, buf->cap - buf->size);
182  if (buf->wpos + len > buf->cap) {
183  len = buf->cap - buf->wpos;
184  }
185  memcpy(buf->buf + buf->wpos, data + bytes_write, len);
186  buf->wpos = (buf->wpos + len) % (buf->cap);
187  bytes_write += len;
188  buf->size += len;
189 
190  /* wake up reader */
191  pthread_cond_signal(&buf->empty);
192  pthread_mutex_unlock(&buf->mutex);
193  }
194  return ISO_SUCCESS;
195 }

References iso_ring_buffer::buf, iso_ring_buffer::cap, iso_ring_buffer::empty, iso_ring_buffer::full, ISO_NULL_POINTER, ISO_SUCCESS, MIN, iso_ring_buffer::mutex, iso_ring_buffer::rend, iso_ring_buffer::size, iso_ring_buffer::times_full, and iso_ring_buffer::wpos.

Referenced by iso_write().

◆ iso_ring_buffer_writer_close()

void iso_ring_buffer_writer_close ( IsoRingBuffer buf,
int  error 
)

Close the buffer (to be called by the writer).

You have to explicitly close the buffer when you don't have more data to write, otherwise reader will be waiting forever.

Parameters
errorWriter has finished prematurely due to an error

Definition at line 252 of file buffer.c.

253 {
254  pthread_mutex_lock(&buf->mutex);
255  buf->wend = error ? 2 : 1;
256 
257  /* ensure no reader is waiting */
258  pthread_cond_signal(&buf->empty);
259  pthread_mutex_unlock(&buf->mutex);
260 }

References iso_ring_buffer::empty, iso_ring_buffer::mutex, and iso_ring_buffer::wend.

Referenced by write_function().