mirror of
https://gitlab.xiph.org/xiph/icecast-server.git
synced 2024-09-08 04:04:48 -04:00
caused significant lock contention with many sources. Further, a single refbuf is never used by more than one source (and hence one thread), so the locking was unneeded. Fix a nasty bug in source.c:_compare_clients() - was casting a void pointer to the wrong type, and hence all the tree-maintaince comparisons were totally wrong (but due to the exact nature of the bug this wasn't causing any active problems until...) Add another admin command to kill a client - remove it using an id. Note that many clients will do auto-reconnect, so this may not be sufficient on its own, we might need a ban (possibly temporary) function. svn path=/trunk/icecast/; revision=4569
124 lines
2.2 KiB
C
124 lines
2.2 KiB
C
/* refbuf.c
|
|
**
|
|
** reference counting buffer implementation
|
|
**
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "refbuf.h"
|
|
|
|
void refbuf_initialize(void)
|
|
{
|
|
}
|
|
|
|
void refbuf_shutdown(void)
|
|
{
|
|
}
|
|
|
|
refbuf_t *refbuf_new(unsigned long size)
|
|
{
|
|
refbuf_t *refbuf;
|
|
|
|
refbuf = (refbuf_t *)malloc(sizeof(refbuf_t));
|
|
refbuf->data = (void *)malloc(size);
|
|
refbuf->len = size;
|
|
refbuf->_count = 1;
|
|
|
|
return refbuf;
|
|
}
|
|
|
|
void refbuf_addref(refbuf_t *self)
|
|
{
|
|
self->_count++;
|
|
}
|
|
|
|
void refbuf_release(refbuf_t *self)
|
|
{
|
|
self->_count--;
|
|
if (self->_count == 0) {
|
|
free(self->data);
|
|
free(self);
|
|
return;
|
|
}
|
|
}
|
|
|
|
void refbuf_queue_add(refbuf_queue_t **queue, refbuf_t *refbuf)
|
|
{
|
|
refbuf_queue_t *node;
|
|
refbuf_queue_t *item = (refbuf_queue_t *)malloc(sizeof(refbuf_queue_t));
|
|
|
|
item->refbuf = refbuf;
|
|
item->next = NULL;
|
|
|
|
if (*queue == NULL) {
|
|
*queue = item;
|
|
(*queue)->total_length = item->refbuf->len;
|
|
} else {
|
|
node = *queue;
|
|
while (node->next) node = node->next;
|
|
node->next = item;
|
|
(*queue)->total_length += item->refbuf->len;
|
|
}
|
|
}
|
|
|
|
refbuf_t *refbuf_queue_remove(refbuf_queue_t **queue)
|
|
{
|
|
refbuf_queue_t *item;
|
|
refbuf_t *refbuf;
|
|
|
|
if (*queue == NULL) return NULL;
|
|
|
|
item = *queue;
|
|
*queue = item->next;
|
|
item->next = NULL;
|
|
|
|
refbuf = item->refbuf;
|
|
item->refbuf = NULL;
|
|
|
|
if(*queue)
|
|
(*queue)->total_length = item->total_length - refbuf->len;
|
|
|
|
free(item);
|
|
|
|
|
|
return refbuf;
|
|
}
|
|
|
|
void refbuf_queue_insert(refbuf_queue_t **queue, refbuf_t *refbuf)
|
|
{
|
|
refbuf_queue_t *item = (refbuf_queue_t *)malloc(sizeof(refbuf_queue_t));
|
|
|
|
item->refbuf = refbuf;
|
|
item->next = *queue;
|
|
if(item->next)
|
|
item->total_length = item->next->total_length + item->refbuf->len;
|
|
else
|
|
item->total_length = item->refbuf->len;
|
|
*queue = item;
|
|
}
|
|
|
|
int refbuf_queue_size(refbuf_queue_t **queue)
|
|
{
|
|
refbuf_queue_t *node = *queue;
|
|
int size = 0;
|
|
|
|
while (node) {
|
|
node = node->next;
|
|
size++;
|
|
}
|
|
|
|
return size;
|
|
}
|
|
|
|
int refbuf_queue_length(refbuf_queue_t **queue)
|
|
{
|
|
if(*queue)
|
|
return (*queue)->total_length;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
|