1/* 2 * (C) 2006-2009 by Pablo Neira Ayuso <pablo@netfilter.org> 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 17 */ 18 19#include "queue.h" 20#include "event.h" 21 22#include <errno.h> 23#include <stdio.h> 24#include <stdlib.h> 25#include <string.h> 26#include <sys/socket.h> 27 28static LIST_HEAD(queue_list); /* list of existing queues */ 29static uint32_t qobjects_num; /* number of active queue objects */ 30 31struct queue * 32queue_create(const char *name, int max_objects, unsigned int flags) 33{ 34 struct queue *b; 35 36 b = calloc(sizeof(struct queue), 1); 37 if (b == NULL) 38 return NULL; 39 40 b->max_elems = max_objects; 41 INIT_LIST_HEAD(&b->head); 42 b->flags = flags; 43 44 if (flags & QUEUE_F_EVFD) { 45 b->evfd = create_evfd(); 46 if (b->evfd == NULL) { 47 free(b); 48 return NULL; 49 } 50 } 51 strncpy(b->name, name, QUEUE_NAMELEN); 52 b->name[QUEUE_NAMELEN-1]='\0'; 53 list_add(&b->list, &queue_list); 54 55 return b; 56} 57 58void queue_destroy(struct queue *b) 59{ 60 list_del(&b->list); 61 if (b->flags & QUEUE_F_EVFD) 62 destroy_evfd(b->evfd); 63 free(b); 64} 65 66void queue_stats_show(int fd) 67{ 68 struct queue *this; 69 int size = 0; 70 char buf[512]; 71 72 size += snprintf(buf+size, sizeof(buf), 73 "allocated queue nodes:\t\t%12u\n\n", 74 qobjects_num); 75 76 list_for_each_entry(this, &queue_list, list) { 77 size += snprintf(buf+size, sizeof(buf), 78 "queue %s:\n" 79 "current elements:\t\t%12u\n" 80 "maximum elements:\t\t%12u\n" 81 "not enough space errors:\t%12u\n\n", 82 this->name, 83 this->num_elems, 84 this->max_elems, 85 this->enospc_err); 86 } 87 send(fd, buf, size, 0); 88} 89 90void queue_node_init(struct queue_node *n, int type) 91{ 92 INIT_LIST_HEAD(&n->head); 93 n->type = type; 94} 95 96void *queue_node_data(struct queue_node *n) 97{ 98 return ((char *)n) + sizeof(struct queue_node); 99} 100 101struct queue_object *queue_object_new(int type, size_t size) 102{ 103 struct queue_object *obj; 104 105 obj = calloc(sizeof(struct queue_object) + size, 1); 106 if (obj == NULL) 107 return NULL; 108 109 obj->qnode.size = size; 110 queue_node_init(&obj->qnode, type); 111 qobjects_num++; 112 113 return obj; 114} 115 116void queue_object_free(struct queue_object *obj) 117{ 118 free(obj); 119 qobjects_num--; 120} 121 122int queue_add(struct queue *b, struct queue_node *n) 123{ 124 if (!list_empty(&n->head)) 125 return 0; 126 127 if (b->num_elems >= b->max_elems) { 128 b->enospc_err++; 129 errno = ENOSPC; 130 return -1; 131 } 132 n->owner = b; 133 list_add_tail(&n->head, &b->head); 134 b->num_elems++; 135 if (b->evfd) 136 write_evfd(b->evfd); 137 return 1; 138} 139 140int queue_del(struct queue_node *n) 141{ 142 if (list_empty(&n->head)) 143 return 0; 144 145 list_del_init(&n->head); 146 n->owner->num_elems--; 147 if (n->owner->evfd) 148 read_evfd(n->owner->evfd); 149 n->owner = NULL; 150 return 1; 151} 152 153struct queue_node *queue_del_head(struct queue *b) 154{ 155 struct queue_node *n = (struct queue_node *) b->head.next; 156 queue_del(n); 157 return n; 158} 159 160int queue_in(struct queue *b, struct queue_node *n) 161{ 162 return b == n->owner; 163} 164 165int queue_get_eventfd(struct queue *b) 166{ 167 return get_read_evfd(b->evfd); 168} 169 170void queue_iterate(struct queue *b, 171 const void *data, 172 int (*iterate)(struct queue_node *n, const void *data2)) 173{ 174 struct list_head *i, *tmp; 175 struct queue_node *n; 176 177 list_for_each_safe(i, tmp, &b->head) { 178 n = (struct queue_node *) i; 179 if (iterate(n, data)) 180 break; 181 } 182} 183 184unsigned int queue_len(const struct queue *b) 185{ 186 return b->num_elems; 187} 188