diff --git a/httperf/ChangeLog b/httperf/ChangeLog index 00b2283..6b0794d 100755 --- a/httperf/ChangeLog +++ b/httperf/ChangeLog @@ -1,3 +1,7 @@ +2007-09-11 Ted Bullock + + * lib/heap.c, lib/heap.h: New generic priority queue data structure + 2007-07-15 Ted Bullock * lib/queue.c, lib/queue.h: New generic queue data structure diff --git a/httperf/src/lib/Makefile.am b/httperf/src/lib/Makefile.am index 1a79bf2..9625e6a 100755 --- a/httperf/src/lib/Makefile.am +++ b/httperf/src/lib/Makefile.am @@ -4,4 +4,4 @@ AM_LDFLAGS = noinst_LIBRARIES = libutil.a libutil_a_SOURCES = getopt.c getopt.h getopt1.c ssl_writev.c generic_types.h \ - queue.c queue.h + queue.c queue.h heap.c heap.h diff --git a/httperf/src/lib/heap.c b/httperf/src/lib/heap.c new file mode 100644 index 0000000..02b93ba --- /dev/null +++ b/httperf/src/lib/heap.c @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2007 Ted Bullock + * + * This file is part of httperf, a web server performance measurment tool. + * + * 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. + * + * In addition, as a special exception, the copyright holders give permission + * to link the code of this work with the OpenSSL project's "OpenSSL" library + * (or with modified versions of it that use the same license as the "OpenSSL" + * library), and distribute linked combinations including the two. You must + * obey the GNU General Public License in all respects for all of the code + * used other than "OpenSSL". If you modify this file, you may extend this + * exception to your version of the file, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * 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., 51 + * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" + +#include +#include + +#include +#include + +#define Minimum_Heap_Size 10 + +struct Heap { + u_long array_size; + u_long num_elements; + heap_compare compare; + Any_Type storage[]; /* c99 Flexible Array Member */ +}; + +struct Heap * +create_heap(u_long size, heap_compare compare_callback) +{ + struct Heap *h; + + if (size < Minimum_Heap_Size) + size = Minimum_Heap_Size; + + /* + * We are using c99 Flexible Array Members so we can do this :) + */ + h = malloc(sizeof(struct Heap) + sizeof(Any_Type) * size); + if (!h) + return NULL; + + h->array_size = size; + h->num_elements = 0; + h->compare = compare_callback; + + return h; +} + +_Bool +is_heap_empty(struct Heap * h) +{ + return h->num_elements == 0; +} + +_Bool +is_heap_full(struct Heap * h) +{ + return h->array_size == h->num_elements; +} + +u_long +num_heap_elements(struct Heap * h) +{ + return h->num_elements; +} + +void +free_heap(struct Heap *h) +{ + if (h != NULL) + free(h); +} + +#define PARENT(i) (i/2) +_Bool +insert(Any_Type a, struct Heap *h) +{ + u_long i, parent; + + if (is_heap_full(h)) + return false; + + i = ++h->num_elements; + + /* + * find the correct place to insert + */ + while ((i > 1) && (*h->compare) (h->storage[PARENT(i)], a)) { + h->storage[i] = h->storage[PARENT(i)]; + i = PARENT(i); + } + h->storage[i] = a; + return true; +} + +static void +percolate(struct Heap *h, u_long hole) +{ + int child; + Any_Type dest_val = h->storage[hole]; + + for (; hole * 2 <= h->num_elements; hole = child) { + child = hole * 2; + if (child != h->num_elements + && (*h->compare) (h->storage[child + 1], + h->storage[child + 1])) + child++; + if ((*h->compare) (h->storage[child + 1], dest_val)) + h->storage[hole] = h->storage[child]; + else + break; + } + h->storage[hole] = dest_val; +} + +Any_Type +remove_min(struct Heap * h) +{ + if(is_heap_empty(h)) + return (Any_Type) 0; + else { + Any_Type min = h->storage[1]; + h->storage[1] = h->storage[h->num_elements--]; + percolate(h, 1); + + return min; + } +} + +Any_Type +poll_min(struct Heap * h) +{ + if(is_heap_empty(h)) + return (Any_Type) 0; + else + return h->storage[1]; +} + +void +heap_for_each(struct Heap *h, heap_for_each_action action) +{ + for(u_long i = 1; i <= h->num_elements; i++) + { + (*action)(h->storage[i]); + } +} diff --git a/httperf/src/lib/heap.h b/httperf/src/lib/heap.h new file mode 100644 index 0000000..f0b58a6 --- /dev/null +++ b/httperf/src/lib/heap.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2007 Ted Bullock + * + * This file is part of httperf, a web server performance measurment tool. + * + * 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. + * + * In addition, as a special exception, the copyright holders give permission + * to link the code of this work with the OpenSSL project's "OpenSSL" library + * (or with modified versions of it that use the same license as the "OpenSSL" + * library), and distribute linked combinations including the two. You must + * obey the GNU General Public License in all respects for all of the code + * used other than "OpenSSL". If you modify this file, you may extend this + * exception to your version of the file, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * 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., 51 + * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef heap_h +#define heap_h + +struct Heap; + +typedef _Bool (*heap_compare) (Any_Type, Any_Type); +typedef void (*heap_for_each_action) (Any_Type); + +struct Heap *create_heap(u_long, heap_compare); +_Bool is_heap_empty(struct Heap *); +_Bool is_heap_full(struct Heap *); +u_long num_heap_elements(struct Heap *); +void free_heap(struct Heap *); + +_Bool insert(Any_Type, struct Heap *); +Any_Type remove_min(struct Heap *); +Any_Type poll_min(struct Heap *); + +void heap_for_each(struct Heap *, heap_for_each_action); + +#endif /* Heap_h */ diff --git a/httperf/src/lib/queue.c b/httperf/src/lib/queue.c index 5c350e9..cecb61b 100644 --- a/httperf/src/lib/queue.c +++ b/httperf/src/lib/queue.c @@ -31,12 +31,9 @@ #include "config.h" #include -#include -#include #include #include -#include #define Minimum_Wheel_Size 10 @@ -71,12 +68,9 @@ create_queue(u_long size) * Again, we are using c99 Flexible Array Members so we can do this :) */ q = malloc(sizeof(struct Queue) + sizeof(Any_Type) * size); - if (!q) { - fprintf(stderr, "%s.create_queue: %s\n", prog_name, - strerror(errno)); - return 0; - } - + if (q == NULL) + return NULL; + q->wheel_size = size; empty_queue(q); @@ -109,16 +103,15 @@ enqueue(Any_Type a, struct Queue *q) { if (is_queue_full(q)) return 0; - else { - q->num_elements++; + + q->num_elements++; - if (++q->last_element == q->wheel_size) { - q->last_element = 0; - } + if (++q->last_element == q->wheel_size) + q->last_element = 0; - q->wheel[q->last_element] = a; - } + q->wheel[q->last_element] = a; + return 1; } void diff --git a/httperf/src/lib/queue.h b/httperf/src/lib/queue.h index e80fac3..a1f075f 100644 --- a/httperf/src/lib/queue.h +++ b/httperf/src/lib/queue.h @@ -41,5 +41,6 @@ int enqueue(Any_Type, struct Queue *); Any_Type get_front(struct Queue *); void dequeue(struct Queue *); Any_Type get_front_and_dequeue(struct Queue *); +void print_vp(struct Queue *); #endif /* queue_h */