diff options
Diffstat (limited to 'src/queue.c')
-rw-r--r-- | src/queue.c | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/src/queue.c b/src/queue.c new file mode 100644 index 0000000..76425b1 --- /dev/null +++ b/src/queue.c @@ -0,0 +1,187 @@ +/* + * (C) 2006-2009 by Pablo Neira Ayuso <pablo@netfilter.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "queue.h" +#include "event.h" + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/socket.h> + +static LIST_HEAD(queue_list); /* list of existing queues */ +static uint32_t qobjects_num; /* number of active queue objects */ + +struct queue * +queue_create(const char *name, int max_objects, unsigned int flags) +{ + struct queue *b; + + b = calloc(sizeof(struct queue), 1); + if (b == NULL) + return NULL; + + b->max_elems = max_objects; + INIT_LIST_HEAD(&b->head); + b->flags = flags; + + if (flags & QUEUE_F_EVFD) { + b->evfd = create_evfd(); + if (b->evfd == NULL) { + free(b); + return NULL; + } + } + strncpy(b->name, name, QUEUE_NAMELEN); + b->name[QUEUE_NAMELEN-1]='\0'; + list_add(&b->list, &queue_list); + + return b; +} + +void queue_destroy(struct queue *b) +{ + list_del(&b->list); + if (b->flags & QUEUE_F_EVFD) + destroy_evfd(b->evfd); + free(b); +} + +void queue_stats_show(int fd) +{ + struct queue *this; + int size = 0; + char buf[512]; + + size += snprintf(buf+size, sizeof(buf), + "allocated queue nodes:\t\t%12u\n\n", + qobjects_num); + + list_for_each_entry(this, &queue_list, list) { + size += snprintf(buf+size, sizeof(buf), + "queue %s:\n" + "current elements:\t\t%12u\n" + "maximum elements:\t\t%12u\n" + "not enough space errors:\t%12u\n\n", + this->name, + this->num_elems, + this->max_elems, + this->enospc_err); + } + send(fd, buf, size, 0); +} + +void queue_node_init(struct queue_node *n, int type) +{ + INIT_LIST_HEAD(&n->head); + n->type = type; +} + +void *queue_node_data(struct queue_node *n) +{ + return ((char *)n) + sizeof(struct queue_node); +} + +struct queue_object *queue_object_new(int type, size_t size) +{ + struct queue_object *obj; + + obj = calloc(sizeof(struct queue_object) + size, 1); + if (obj == NULL) + return NULL; + + obj->qnode.size = size; + queue_node_init(&obj->qnode, type); + qobjects_num++; + + return obj; +} + +void queue_object_free(struct queue_object *obj) +{ + free(obj); + qobjects_num--; +} + +int queue_add(struct queue *b, struct queue_node *n) +{ + if (!list_empty(&n->head)) + return 0; + + if (b->num_elems >= b->max_elems) { + b->enospc_err++; + errno = ENOSPC; + return -1; + } + n->owner = b; + list_add_tail(&n->head, &b->head); + b->num_elems++; + if (b->evfd) + write_evfd(b->evfd); + return 1; +} + +int queue_del(struct queue_node *n) +{ + if (list_empty(&n->head)) + return 0; + + list_del_init(&n->head); + n->owner->num_elems--; + if (n->owner->evfd) + read_evfd(n->owner->evfd); + n->owner = NULL; + return 1; +} + +struct queue_node *queue_del_head(struct queue *b) +{ + struct queue_node *n = (struct queue_node *) b->head.next; + queue_del(n); + return n; +} + +int queue_in(struct queue *b, struct queue_node *n) +{ + return b == n->owner; +} + +int queue_get_eventfd(struct queue *b) +{ + return get_read_evfd(b->evfd); +} + +void queue_iterate(struct queue *b, + const void *data, + int (*iterate)(struct queue_node *n, const void *data2)) +{ + struct list_head *i, *tmp; + struct queue_node *n; + + list_for_each_safe(i, tmp, &b->head) { + n = (struct queue_node *) i; + if (iterate(n, data)) + break; + } +} + +unsigned int queue_len(const struct queue *b) +{ + return b->num_elems; +} |