MythTV  0.28pre
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Groups Pages
ringbuffer.c
Go to the documentation of this file.
1 /*
2  * ringbuffer.c
3  *
4  *
5  * Copyright (C) 2003 Marcus Metzler <mocm@metzlerbros.de>
6  * Metzler Brothers Systementwicklung GbR
7  * Changes to use MythTV logging
8  * Copyright (C) 2011 Gavin Hurlbut <ghurlbut@mythtv.org>
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * General Public License for more details.
20  *
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25  * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
26  *
27  */
28 
29 #include <stdlib.h>
30 #include <string.h>
31 #include "ringbuffer.h"
32 #include "pes.h"
33 
34 #include "mythlogging.h"
35 
36 #define DEBUG 1
37 int ring_init (ringbuffer *rbuf, int size)
38 {
39  if (size > 0){
40  rbuf->size = size;
41  if( !(rbuf->buffer = (uint8_t *) malloc(sizeof(uint8_t)*size)) ){
42  LOG(VB_GENERAL, LOG_ERR,
43  "Not enough memory for ringbuffer");
44  return -1;
45  }
46  } else {
47  LOG(VB_GENERAL, LOG_ERR, "Wrong size for ringbuffer");
48  return -1;
49  }
50  rbuf->read_pos = 0;
51  rbuf->write_pos = 0;
52  return 0;
53 }
54 
55 int ring_reinit (ringbuffer *rbuf, int size)
56 {
57  if (size > (int)(rbuf->size)) {
58  uint8_t *tmpalloc = (uint8_t *) realloc(rbuf->buffer,
59  sizeof(uint8_t)*size);
60  if (! tmpalloc)
61  return -1;
62  rbuf->buffer = tmpalloc;
63  if (rbuf->write_pos < rbuf->read_pos)
64  {
65  unsigned int delta = size - rbuf->size;
66  memmove(rbuf->buffer + rbuf->read_pos + delta,
67  rbuf->buffer + rbuf->read_pos,
68  rbuf->size - rbuf->read_pos);
69  rbuf->read_pos += delta;
70  }
71  rbuf->size = size;
72  }
73  return 0;
74 }
76 {
77  rbuf->read_pos = 0;
78  rbuf->write_pos = 0;
79 }
80 
81 
82 
84 {
85  free(rbuf->buffer);
86 }
87 
88 
89 int ring_write(ringbuffer *rbuf, uint8_t *data, int count)
90 {
91 
92  int free, pos, rest;
93 
94  if (count <=0 ) return 0;
95  pos = rbuf->write_pos;
96  rest = rbuf->size - pos;
97  free = ring_free(rbuf);
98 
99  if ( free < count ){
100  if (DEBUG)
101  LOG(VB_GENERAL, LOG_ERR,
102  "ringbuffer overflow %d<%d %d",
103  free, count, rbuf->size);
104  return FULL_BUFFER;
105  }
106 
107  if (count >= rest){
108  memcpy (rbuf->buffer+pos, data, rest);
109  if (count - rest)
110  memcpy (rbuf->buffer, data+rest, count - rest);
111  rbuf->write_pos = count - rest;
112  } else {
113  memcpy (rbuf->buffer+pos, data, count);
114  rbuf->write_pos += count;
115  }
116 
117  if (DEBUG>1)
118  LOG(VB_GENERAL, LOG_ERR, "Buffer empty %.2f%%",
119  ring_free(rbuf)*100.0/rbuf->size);
120  return count;
121 }
122 
123 int ring_peek(ringbuffer *rbuf, uint8_t *data, unsigned int count, uint32_t off)
124 {
125 
126  unsigned int avail, pos, rest;
127 
128  if (off+count > rbuf->size || off+count >ring_avail(rbuf))
129  return -1;
130  pos = (rbuf->read_pos+off)%rbuf->size;
131  rest = rbuf->size - pos ;
132  avail = ring_avail(rbuf);
133 
134 
135  if ( avail < count ){
136 #if 0
137  if (DEBUG)
138  LOG(VB_GENERAL, LOG_ERR,
139  "ringbuffer peek underflow %d<%d %d %d",
140  avail, count, pos, rbuf->write_pos);
141 #endif
142  return EMPTY_BUFFER;
143  }
144 
145  if ( count < rest ){
146  memcpy(data, rbuf->buffer+pos, count);
147  } else {
148  memcpy(data, rbuf->buffer+pos, rest);
149  if ( count - rest)
150  memcpy(data+rest, rbuf->buffer, count - rest);
151  }
152 
153  return count;
154 }
155 
156 int ring_poke(ringbuffer *rbuf, uint8_t *data, unsigned int count, uint32_t off)
157 {
158 
159  unsigned int avail, pos, rest;
160 
161  if (off+count > rbuf->size || off+count >ring_avail(rbuf))
162  return -1;
163  pos = (rbuf->read_pos+off)%rbuf->size;
164  rest = rbuf->size - pos ;
165  avail = ring_avail(rbuf);
166 
167 
168  if ( avail < count ){
169 #if 0
170  if (DEBUG)
171  LOG(VB_GENERAL, LOG_ERR,
172  "ringbuffer peek underflow %d<%d %d %d",
173  avail, count, pos, rbuf->write_pos);
174 #endif
175  return EMPTY_BUFFER;
176  }
177 
178  if ( count < rest ){
179  memcpy(rbuf->buffer+pos, data, count);
180  } else {
181  memcpy(rbuf->buffer+pos, data, rest);
182  if ( count - rest)
183  memcpy(rbuf->buffer, data+rest, count - rest);
184  }
185 
186  return count;
187 }
188 
189 int ring_read(ringbuffer *rbuf, uint8_t *data, int count)
190 {
191 
192  int avail, pos, rest;
193 
194  if (count <=0 ) return 0;
195  pos = rbuf->read_pos;
196  rest = rbuf->size - pos;
197  avail = ring_avail(rbuf);
198 
199  if ( avail < count ){
200 #if 0
201  if (DEBUG)
202  LOG(VB_GENERAL, LOG_ERR,
203  "ringbuffer underflow %d<%d %d \n",
204  avail, count, rbuf->size);
205 #endif
206  return EMPTY_BUFFER;
207  }
208 
209  if ( count < rest ){
210  memcpy(data, rbuf->buffer+pos, count);
211  rbuf->read_pos += count;
212  } else {
213  memcpy(data, rbuf->buffer+pos, rest);
214  if ( count - rest)
215  memcpy(data+rest, rbuf->buffer, count - rest);
216  rbuf->read_pos = count - rest;
217  }
218 
219  if (DEBUG>1)
220  LOG(VB_GENERAL, LOG_ERR, "Buffer empty %.2f%%",
221  ring_free(rbuf)*100.0/rbuf->size);
222  return count;
223 }
224 
225 int ring_skip(ringbuffer *rbuf, int count)
226 {
227 
228  int avail, pos, rest;
229 
230  if (count <=0 ) return -1;
231  pos = rbuf->read_pos;
232  rest = rbuf->size - pos;
233  avail = ring_avail(rbuf);
234 
235  if ( avail < count ){
236 #if 0
237  LOG(VB_GENERAL, LOG_ERR,
238  "ringbuffer skip underflow %d<%d %d %d\n",
239  avail, count, pos, rbuf->write_pos);
240 #endif
241  return EMPTY_BUFFER;
242  }
243  if ( count < rest ){
244  rbuf->read_pos += count;
245  } else {
246  rbuf->read_pos = count - rest;
247  }
248 
249  if (DEBUG>1)
250  LOG(VB_GENERAL, LOG_ERR, "Buffer empty %.2f%%",
251  ring_free(rbuf)*100.0/rbuf->size);
252  return count;
253 }
254 
255 
256 
257 int ring_write_file(ringbuffer *rbuf, int fd, int count)
258 {
259 
260  int free, pos, rest, rr;
261 
262  if (count <=0 ) return 0;
263  pos = rbuf->write_pos;
264  rest = rbuf->size - pos;
265  free = ring_free(rbuf);
266 
267  if ( free < count ){
268  if (DEBUG)
269  LOG(VB_GENERAL, LOG_ERR,
270  "ringbuffer overflow %d<%d %d %d\n",
271  free, count, pos, rbuf->read_pos);
272  return FULL_BUFFER;
273  }
274 
275  if (count >= rest){
276  rr = read (fd, rbuf->buffer+pos, rest);
277  if (rr == rest && count - rest)
278  rr += read (fd, rbuf->buffer, count - rest);
279  if (rr >=0)
280  rbuf->write_pos = (pos + rr) % rbuf->size;
281  } else {
282  rr = read (fd, rbuf->buffer+pos, count);
283  if (rr >=0)
284  rbuf->write_pos += rr;
285  }
286 
287  if (DEBUG>1)
288  LOG(VB_GENERAL, LOG_ERR, "Buffer empty %.2f%%",
289  ring_free(rbuf)*100.0/rbuf->size);
290  return rr;
291 }
292 
293 
294 
295 int ring_read_file(ringbuffer *rbuf, int fd, int count)
296 {
297 
298  int avail, pos, rest, rr;
299 
300  if (count <=0 ) return -1;
301  pos = rbuf->read_pos;
302  rest = rbuf->size - pos;
303  avail = ring_avail(rbuf);
304 
305  if ( avail < count ){
306 #if 0
307  if (DEBUG)
308  LOG(VB_GENERAL, LOG_ERR,
309  "ringbuffer underflow %d<%d %d %d",
310  avail, count, pos, rbuf->write_pos);
311 #endif
312  return EMPTY_BUFFER;
313  }
314 
315  if (count >= rest){
316  rr = write (fd, rbuf->buffer+pos, rest);
317  if (rr == rest && count - rest)
318  rr += write (fd, rbuf->buffer, count - rest);
319  if (rr >=0)
320  rbuf->read_pos = (pos + rr) % rbuf->size;
321  } else {
322  rr = write (fd, rbuf->buffer+pos, count);
323  if (rr >=0)
324  rbuf->read_pos += rr;
325  }
326 
327 
328  if (DEBUG>1)
329  LOG(VB_GENERAL, LOG_ERR, "Buffer empty %.2f%%",
330  ring_free(rbuf)*100.0/rbuf->size);
331  return rr;
332 }
333 
334 
335 static void show(uint8_t *buf, int length)
336 {
337  int i,j,r;
338  uint8_t temp[8];
339  uint8_t buffer[100];
340  buffer[0] = '\0';
341 
342  for (i=0; i<length; i+=16){
343  for (j=0; j < 8 && j+i<length; j++)
344  {
345  sprintf(temp, "0x%02x ", (int)(buf[i+j]));
346  strcat(buffer, temp);
347  }
348  for (r=j; r<8; r++)
349  strcat(buffer, " ");
350 
351  strcat(buffer," ");
352 
353  for (j=8; j < 16 && j+i<length; j++)
354  {
355  sprintf(temp, "0x%02x ", (int)(buf[i+j]));
356  strcat(buffer, temp);
357  }
358  for (r=j; r<16; r++)
359  strcat(buffer, " ");
360 
361  for (j=0; j < 16 && j+i<length; j++){
362  switch(buf[i+j]){
363  case '0'...'Z':
364  case 'a'...'z':
365  sprintf(temp, "%c", buf[i+j]);
366  break;
367  default:
368  sprintf(temp, ".");
369  }
370  strcat(buffer, temp);
371  }
372  LOG(VB_GENERAL, LOG_INFO, buffer);
373  }
374 }
375 
376 void ring_show(ringbuffer *rbuf, unsigned int count, uint32_t off)
377 {
378 
379  unsigned int avail, pos, rest;
380 
381  if (off+count > rbuf->size || off+count >ring_avail(rbuf))
382  return;
383  pos = (rbuf->read_pos+off)%rbuf->size;
384  rest = rbuf->size - pos ;
385  avail = ring_avail(rbuf);
386 
387 
388  if ( avail < count ){
389 #if 0
390  if (DEBUG)
391  LOG(VB_GENERAL, LOG_ERR,
392  "ringbuffer peek underflow %d<%d %d %d\n",
393  avail, count, pos, rbuf->write_pos);
394 #endif
395  return;
396  }
397 
398  if ( count < rest ){
399  show(rbuf->buffer+pos, count);
400  } else {
401  show(rbuf->buffer+pos, rest);
402  if ( count - rest)
403  show(rbuf->buffer, count - rest);
404  }
405 }
406 
407 
408 int dummy_init(dummy_buffer *dbuf, int s)
409 {
410  dbuf->size = s;
411  dbuf->fill = 0;
412  if (ring_init(&dbuf->time_index, DBUF_INDEX*sizeof(uint64_t)) < 0)
413  return -1;
414  if (ring_init(&dbuf->data_index, DBUF_INDEX*sizeof(int32_t)) < 0)
415  return -1;
416 
417  return 0;
418 }
419 
421 {
422  ring_destroy(&dbuf->time_index);
423  ring_destroy(&dbuf->data_index);
424 }
425 
427 {
428  dbuf->fill = 0;
429  ring_clear(&dbuf->time_index);
430  ring_clear(&dbuf->data_index);
431 }
432 
433 int dummy_add(dummy_buffer *dbuf, uint64_t time, uint32_t size)
434 {
435  if (dummy_space(dbuf) < size) return -1;
436 #if 0
437  LOG(VB_GENERAL, LOG_INFO, "add %d ", dummy_space(dbuf));
438 #endif
439  dbuf->fill += size;
440  if (ring_write(&dbuf->time_index, (uint8_t *)&time, sizeof(uint64_t)) < 0)
441  return -2;
442  if (ring_write(&dbuf->data_index, (uint8_t *)&size, sizeof(uint32_t)) < 0)
443  return -3;
444 #if 0
445  LOG(VB_GENERAL, LOG_INFO, " - %d = "%d", size, dummy_space(dbuf));
446 #endif
447  return size;
448 }
449 
450 int dummy_delete(dummy_buffer *dbuf, uint64_t time)
451 {
452  uint64_t rtime;
453  uint32_t size;
454  int ex=0;
455  uint32_t dsize=0;
456 
457  do {
458  if (ring_peek(&dbuf->time_index,(uint8_t *) &rtime,
459  sizeof(uint64_t), 0)<0){
460  if (dsize) break;
461  else return -1;
462  }
463  if (ptscmp(rtime,time) < 0){
464  ring_read(&dbuf->time_index,(uint8_t *) &rtime,
465  sizeof(uint64_t));
466  ring_read(&dbuf->data_index,(uint8_t *) &size,
467  sizeof(uint32_t));
468  dsize += size;
469  } else ex = 1;
470  } while (!ex);
471 #if 0
472  LOG(VB_GENERAL, LOG_INFO, "delete %d ", dummy_space(dbuf));
473 #endif
474  dbuf->fill -= dsize;
475 #if 0
476  LOG(VB_GENERAL, LOG_INFO, " + %d = %d", dsize, dummy_space(dbuf));
477 #endif
478 
479  return dsize;
480 }
481 
482 static void dummy_print(dummy_buffer *dbuf)
483 {
484  int i;
485  uint64_t rtime;
486  uint32_t size;
487  int avail = ring_avail(&dbuf->time_index) / sizeof(uint64_t);
488  for(i = 0; i < avail; i++) {
489  ring_peek(&dbuf->time_index,(uint8_t *) &rtime,
490  sizeof(uint64_t), i * sizeof(uint64_t));
491  ring_peek(&dbuf->data_index,(uint8_t *) &size,
492  sizeof(uint32_t), i * sizeof(uint32_t));
493 
494  LOG(VB_GENERAL, LOG_INFO, "%d : %llu %u", i,
495  (long long unsigned int)rtime, size);
496  }
497  LOG(VB_GENERAL, LOG_INFO, "Used: %d Free: %d data-free: %d", avail,
498  1000-avail, dbuf->size - dbuf->fill);
499 }
GLuint buffer
MYTH_GLsizeiptr const GLvoid * data
static unsigned int ring_free(ringbuffer *rbuf)
int ring_write(ringbuffer *rbuf, uint8_t *data, int count)
Definition: ringbuffer.c:89
void ring_destroy(ringbuffer *rbuf)
Definition: ringbuffer.c:83
return memcpy(dest, src, len)
int ring_write_file(ringbuffer *rbuf, int fd, int count)
Definition: ringbuffer.c:257
int dummy_add(dummy_buffer *dbuf, uint64_t time, uint32_t size)
Definition: ringbuffer.c:433
void ring_show(ringbuffer *rbuf, unsigned int count, uint32_t off)
Definition: ringbuffer.c:376
voidpf void * buf
Definition: ioapi.h:136
int ring_read(ringbuffer *rbuf, uint8_t *data, int count)
Definition: ringbuffer.c:189
static unsigned int ring_avail(ringbuffer *rbuf)
static void show(uint8_t *buf, int length)
Definition: ringbuffer.c:335
BOOL FAR PASCAL short short long d
Definition: minilzo.cpp:2526
void dummy_destroy(dummy_buffer *dbuf)
Definition: ringbuffer.c:420
void dummy_clear(dummy_buffer *dbuf)
Definition: ringbuffer.c:426
int ring_peek(ringbuffer *rbuf, uint8_t *data, unsigned int count, uint32_t off)
Definition: ringbuffer.c:123
return s
Definition: minilzo.cpp:2409
int ring_reinit(ringbuffer *rbuf, int size)
Definition: ringbuffer.c:55
void ring_clear(ringbuffer *rbuf)
Definition: ringbuffer.c:75
int dummy_init(dummy_buffer *dbuf, int s)
Definition: ringbuffer.c:408
return memmove(dest, src, len)
static uint32_t dummy_space(dummy_buffer *dbuf)
unsigned char r
Definition: ParseText.cpp:339
def write
Definition: mythburn.py:279
int ring_skip(ringbuffer *rbuf, int count)
Definition: ringbuffer.c:225
int ring_init(ringbuffer *rbuf, int size)
Definition: ringbuffer.c:37
int ring_read_file(ringbuffer *rbuf, int fd, int count)
Definition: ringbuffer.c:295
lzo_uint lzo_uint size
Definition: lzoconf.h:273
int ring_poke(ringbuffer *rbuf, uint8_t *data, unsigned int count, uint32_t off)
Definition: ringbuffer.c:156