summaryrefslogtreecommitdiff
path: root/src/queue.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/queue.c')
-rw-r--r--src/queue.c187
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;
+}