fr_io_client_t *client;
fr_io_pending_packet_t *pending;
- client = fr_heap_pop(thread->pending_clients);
+ client = fr_heap_pop(&thread->pending_clients);
if (!client) {
/*
* 99% of the time we don't have pending clients.
return NULL;
}
- pending = fr_heap_pop(client->pending);
+ pending = fr_heap_pop(&client->pending);
fr_assert(pending != NULL);
/*
* the heap.
*/
if (fr_heap_num_elements(client->pending) > 0) {
- if (fr_heap_insert(thread->pending_clients, client) < 0) {
+ if (fr_heap_insert(&thread->pending_clients, client) < 0) {
fr_assert(0 == 1);
}
}
* Insert the pending packet for this client. If it
* fails, silently discard the packet.
*/
- if (fr_heap_insert(client->pending, pending) < 0) {
+ if (fr_heap_insert(&client->pending, pending) < 0) {
talloc_free(pending);
return NULL;
}
if (client->pending) TALLOC_FREE(client->pending);
(void) fr_trie_remove_by_key(client->thread->trie, &client->src_ipaddr.addr, client->src_ipaddr.prefix);
- (void) fr_heap_extract(client->thread->alive_clients, client);
+ (void) fr_heap_extract(&client->thread->alive_clients, client);
return 0;
}
return -1;
}
- pending = fr_heap_pop(connection->client->pending);
+ pending = fr_heap_pop(&connection->client->pending);
} else if (thread->pending_clients) {
pending = pending_packet_pop(thread);
* Track the live clients so that we can clean
* them up.
*/
- (void) fr_heap_insert(thread->alive_clients, client);
+ (void) fr_heap_insert(&thread->alive_clients, client);
client->pending_id = -1;
/*
}
fr_assert(client->pending_id < 0);
- (void) fr_heap_insert(thread->pending_clients, client);
+ (void) fr_heap_insert(&thread->pending_clients, client);
finish:
/*
lm = fr_message_localize(nr, &cd.m, sizeof(cd));
if (!lm) return;
- if (fr_heap_insert(nr->replies, lm) < 0) {
+ if (fr_heap_insert(&nr->replies, lm) < 0) {
fr_message_done(lm);
}
}
* Ensure that heap insert works.
*/
cd->channel.heap_id = 0;
- if (fr_heap_insert(nr->replies, cd) < 0) {
+ if (fr_heap_insert(&nr->replies, cd) < 0) {
fr_message_done(&cd->m);
fr_assert(0 == 1);
}
s->pending = NULL;
} else {
- cd = fr_heap_pop(s->waiting);
+ cd = fr_heap_pop(&s->waiting);
}
while (cd != NULL) {
/*
* Grab the net entry.
*/
- cd = fr_heap_pop(s->waiting);
+ cd = fr_heap_pop(&s->waiting);
}
/*
/*
* Clean up any queued entries.
*/
- while ((cd = fr_heap_pop(s->waiting)) != NULL) {
+ while ((cd = fr_heap_pop(&s->waiting)) != NULL) {
fr_message_done(&cd->m);
}
* Pull the replies off of our global heap, and try to
* push them to the individual sockets.
*/
- while ((cd = fr_heap_pop(nr->replies)) != NULL) {
+ while ((cd = fr_heap_pop(&nr->replies)) != NULL) {
fr_listen_t *li;
fr_network_socket_t *s;
*/
if (!s->pending) {
fr_assert(!s->blocked);
- (void) fr_heap_insert(s->waiting, cd);
+ (void) fr_heap_insert(&s->waiting, cd);
fr_network_write(nr->el, s->listen->fd, 0, s);
}
}
* @todo - call transport "done" for the reply, so that
* it knows the replies are done, too.
*/
- while ((cd = fr_heap_pop(nr->replies)) != NULL) {
+ while ((cd = fr_heap_pop(&nr->replies)) != NULL) {
fr_message_done(&cd->m);
}
worker->num_active++;
fr_assert(!fr_heap_entry_inserted(request->runnable_id));
- (void) fr_heap_insert(worker->runnable, request);
+ (void) fr_heap_insert(&worker->runnable, request);
if (!worker->ev_cleanup) worker_max_request_timer(worker);
}
* yank it back out, so it's not "runnable"
* when we call request done.
*/
- if (fr_heap_entry_inserted(request->runnable_id)) fr_heap_extract(worker->runnable, request);
+ if (fr_heap_entry_inserted(request->runnable_id)) fr_heap_extract(&worker->runnable, request);
/*
* The interpreter doesn't currently fix
fr_worker_t *worker = uctx;
RDEBUG3("Request marked as runnable");
- fr_heap_insert(worker->runnable, request);
+ fr_heap_insert(&worker->runnable, request);
}
/** Interpreter yielded request
* every request.
*/
while (fr_time_delta_lt(fr_time_sub(now, start), fr_time_delta_wrap(NSEC / 100000)) &&
- ((request = fr_heap_pop(worker->runnable)) != NULL)) {
+ ((request = fr_heap_pop(&worker->runnable)) != NULL)) {
REQUEST_VERIFY(request);
fr_assert(!fr_heap_entry_inserted(request->runnable_id));
MEM(h = talloc_zero(frame->heap, cf_file_heap_t));
MEM(h->filename = talloc_typed_strdup(h, stack->buff[1]));
h->heap_id = 0;
- (void) fr_heap_insert(frame->heap, h);
+ (void) fr_heap_insert(&frame->heap, h);
}
closedir(dir);
CONF_SECTION *parent = frame->current;
cf_file_heap_t *h;
- h = fr_heap_pop(frame->heap);
+ h = fr_heap_pop(&frame->heap);
if (!h) {
/*
* Done reading the directory entry. Close it, and go
* The connection pool is starting up. Insert the
* connection into the heap.
*/
- if (!in_use) fr_heap_insert(pool->heap, this);
+ if (!in_use) fr_heap_insert(&pool->heap, this);
connection_link_head(pool, this);
/*
* Connection isn't used, remove it from the heap.
*/
- fr_heap_extract(pool->heap, this);
+ fr_heap_extract(&pool->heap, this);
}
fr_pool_trigger_exec(pool, "close");
* heap and use it.
*/
if (this) {
- fr_heap_extract(pool->heap, this);
+ fr_heap_extract(&pool->heap, this);
goto do_return;
}
* gradually expired), or when we released it (allowing
* the maximum amount of time between connection use).
*/
- fr_heap_insert(pool->heap, this);
+ fr_heap_insert(&pool->heap, this);
fr_assert(pool->state.active != 0);
pool->state.active--;
#define REQUEST_EXTRACT_BACKLOG(_treq) \
do { \
int _ret; \
- _ret = fr_heap_extract((_treq)->pub.trunk->backlog, _treq); \
+ _ret = fr_heap_extract(&(_treq)->pub.trunk->backlog, _treq); \
if (!fr_cond_assert_msg(_ret == 0, "Failed extracting conn from backlog heap: %s", fr_strerror())) break; \
} while (0)
#define REQUEST_EXTRACT_PENDING(_treq) \
do { \
int _ret; \
- _ret = fr_heap_extract((_treq)->pub.tconn->pending, _treq); \
+ _ret = fr_heap_extract(&(_treq)->pub.tconn->pending, _treq); \
if (!fr_cond_assert_msg(_ret == 0, "Failed extracting conn from pending heap: %s", fr_strerror())) break; \
} while (0)
}
REQUEST_STATE_TRANSITION(FR_TRUNK_REQUEST_STATE_BACKLOG);
- fr_heap_insert(trunk->backlog, treq); /* Insert into the backlog heap */
+ fr_heap_insert(&trunk->backlog, treq); /* Insert into the backlog heap */
/*
* A new request has entered the trunk.
ROPTIONAL(RDEBUG, DEBUG3, "[%" PRIu64 "] Trunk connection assigned request %"PRIu64,
tconn->pub.conn->id, treq->id);
}
- fr_heap_insert(tconn->pending, treq);
+ fr_heap_insert(&tconn->pending, treq);
/*
* A new request has entered the trunk.
RDEBUG3("Initialising internal synchronous request");
unlang_interpret_set(request, intps->intp);
- fr_heap_insert(intps->runnable, request);
+ fr_heap_insert(&intps->runnable, request);
}
/** External request is now complete
RDEBUG3("Stopped detached request");
- fr_heap_extract(intps->runnable, request);
+ fr_heap_extract(&intps->runnable, request);
}
/** Request is now runnable
{
unlang_interpret_synchronous_t *intps = uctx;
- fr_heap_insert(intps->runnable, request);
+ fr_heap_insert(&intps->runnable, request);
}
/** Interpreter yielded request
* request, THEN we're guaranteed that there is
* still a timer event left.
*/
- sub_request = fr_heap_pop(intps->runnable);
+ sub_request = fr_heap_pop(&intps->runnable);
if (!sub_request) {
DEBUG3("No pending requests (%u yielded)", intps->yielded);
continue;
* freed.
*/
if (!call->ephemeral) {
- if (fr_heap_entry_inserted(xi->idx)) fr_heap_extract(xlat_inst_tree, xi);
+ if (fr_heap_entry_inserted(xi->idx)) fr_heap_extract(&xlat_inst_tree, xi);
if (fr_heap_num_elements(xlat_inst_tree) == 0) TALLOC_FREE(xlat_inst_tree);
}
DEBUG3("Instantiating xlat \"%s\" node %p, instance %p, new thread instance %p",
call->func->name, xt->node, xi->data, xt);
- ret = fr_heap_insert(xlat_thread_inst_tree, xt);
+ ret = fr_heap_insert(&xlat_thread_inst_tree, xt);
if (!fr_cond_assert(ret == 0)) {
error:
TALLOC_FREE(xlat_thread_inst_tree); /* Reset the tree on error */
*/
node->call.id = call_id++;
- ret = fr_heap_insert(xlat_inst_tree, call->inst);
+ ret = fr_heap_insert(&xlat_inst_tree, call->inst);
if (!fr_cond_assert(ret == 0)) {
TALLOC_FREE(call->inst);
return -1;
* is freed, so we need to check there's
* still a heap to pass to fr_heap_pop.
*/
- while (xlat_inst_tree && (xi = fr_heap_pop(xlat_inst_tree))) talloc_free(xi);
+ while (xlat_inst_tree && (xi = fr_heap_pop(&xlat_inst_tree))) talloc_free(xi);
}
RCSID("$Id$")
#define _HEAP_PRIVATE 1
+#include <freeradius-devel/util/debug.h>
#include <freeradius-devel/util/heap.h>
+#include <freeradius-devel/util/misc.h>
#include <freeradius-devel/util/strerror.h>
-#include <freeradius-devel/util/debug.h>
#define INITIAL_CAPACITY 2048
#define HEAP_RIGHT(_x) (2 * (_x) + 1 )
#define HEAP_SWAP(_a, _b) { void *_tmp = _a; _a = _b; _b = _tmp; }
-static void fr_heap_bubble(fr_heap_ext_t *h, fr_heap_index_t child);
+static void fr_heap_bubble(fr_heap_t *h, fr_heap_index_t child);
/** Return how many bytes need to be allocated to hold a heap of a given size
*
*/
size_t fr_heap_pre_alloc_size(unsigned int count)
{
- return sizeof(fr_heap_t) + sizeof(fr_heap_ext_t) + sizeof(void *) * count;
+ return sizeof(fr_heap_t) + sizeof(void *) * count;
}
fr_heap_t *_fr_heap_alloc(TALLOC_CTX *ctx, fr_heap_cmp_t cmp, char const *type, size_t offset, unsigned int init)
{
- fr_heap_t *hp;
- fr_heap_ext_t *h;
+ fr_heap_t *h;
if (!init) init = INITIAL_CAPACITY;
- hp = talloc(ctx, fr_heap_t);
- if (unlikely(!hp)) return NULL;
-
/*
* For small heaps (< 40 elements) the
* increase in memory locality gives us
* a 100% performance increase
* (talloc headers are big);
*/
- h = (fr_heap_ext_t *)talloc_array(hp, uint8_t, sizeof(fr_heap_ext_t) + (sizeof(void *) * (init + 1)));
+ h = (fr_heap_t *)talloc_array(ctx, uint8_t, sizeof(fr_heap_t) + (sizeof(void *) * (init + 1)));
if (unlikely(!h)) return NULL;
- talloc_set_type(h, fr_heap_ext_t);
+ talloc_set_type(h, fr_heap_t);
- *h = (fr_heap_ext_t){
+ *h = (fr_heap_t){
.size = init,
+ .min = init,
.type = type,
.cmp = cmp,
.offset = offset
*/
h->p[0] = (void *)UINTPTR_MAX;
- *hp = h;
-
- return hp;
+ return h;
}
-static inline CC_HINT(always_inline, nonnull) fr_heap_index_t index_get(fr_heap_ext_t *h, void *data)
+static inline CC_HINT(always_inline, nonnull) fr_heap_index_t index_get(fr_heap_t *h, void *data)
{
return *((fr_heap_index_t const *)(((uint8_t const *)data) + h->offset));
}
-static inline CC_HINT(always_inline, nonnull) void index_set(fr_heap_ext_t *h, void *data, fr_heap_index_t idx)
+static inline CC_HINT(always_inline, nonnull) void index_set(fr_heap_t *h, void *data, fr_heap_index_t idx)
{
*((fr_heap_index_t *)(((uint8_t *)data) + h->offset)) = idx;
}
#define OFFSET_SET(_heap, _idx) index_set(_heap, _heap->p[_idx], _idx);
#define OFFSET_RESET(_heap, _idx) index_set(_heap, _heap->p[_idx], 0);
+static inline CC_HINT(always_inline)
+int realloc_heap(fr_heap_t **hp, unsigned int n_size)
+{
+ fr_heap_t *h = *hp;
+
+ h = (fr_heap_t *)talloc_realloc(hp, h, uint8_t, sizeof(fr_heap_t) + (sizeof(void *) * (n_size + 1)));
+ if (unlikely(!h)) {
+ fr_strerror_printf("Failed expanding heap to %u elements (%u bytes)",
+ n_size, (n_size * (unsigned int)sizeof(void *)));
+ return -1;
+ }
+ talloc_set_type(h, fr_heap_t);
+ h->size = n_size;
+
+ *hp = h;
+
+ return 0;
+}
+
+
/** Insert a new element into the heap
*
* Insert element in heap. Normally, p != NULL, we insert p in a
* heap is also stored in the element itself at the given offset
* in bytes.
*
- * @param[in] hp The heap to insert an element into.
+ * @param[in,out] hp The heap to extract an element from.
+ * A new pointer value will be written to hp
+ * if the heap is resized.
* @param[in] data Data to insert into the heap.
* @return
* - 0 on success.
* - -1 on failure (heap full or malloc error).
*/
-int fr_heap_insert(fr_heap_t *hp, void *data)
+int fr_heap_insert(fr_heap_t **hp, void *data)
{
- fr_heap_ext_t *h = *hp;
+ fr_heap_t *h = *hp;
fr_heap_index_t child;
child = index_get(h, data);
n_size = h->size * 2;
}
- h = (fr_heap_ext_t *)talloc_realloc(hp, h, uint8_t, sizeof(fr_heap_ext_t) + (sizeof(void *) * (n_size + 1)));
- if (unlikely(!h)) {
- fr_strerror_printf("Failed expanding heap to %u elements (%u bytes)",
- n_size, (n_size * (unsigned int)sizeof(void *)));
- return -1;
- }
- talloc_set_type(h, fr_heap_ext_t);
- h->size = n_size;
+ if (realloc_heap(&h, n_size) < 0) return -1;
+
*hp = h;
}
return 0;
}
-static inline CC_HINT(always_inline) void fr_heap_bubble(fr_heap_ext_t *h, fr_heap_index_t child)
+static inline CC_HINT(always_inline) void fr_heap_bubble(fr_heap_t *h, fr_heap_index_t child)
{
if (!fr_cond_assert(child > 0)) return;
/** Remove a node from the heap
*
- * @param[in] hp The heap to extract an element from.
+ * @param[in,out] hp The heap to extract an element from.
+ * A new pointer value will be written to hp
+ * if the heap is resized.
* @param[in] data Data to extract from the heap.
* @return
* - 0 on success.
* - -1 on failure (no elements or data not found).
*/
-int fr_heap_extract(fr_heap_t *hp, void *data)
+int fr_heap_extract(fr_heap_t **hp, void *data)
{
- fr_heap_ext_t *h = *hp;
+ fr_heap_t *h = *hp;
fr_heap_index_t parent, child, max;
/*
}
h->num_elements--;
+ /*
+ * If the number of elements in the heap is half
+ * what we need, shrink the heap back.
+ */
+ if ((h->num_elements * 2) < h->size) {
+ unsigned int n_size = ROUND_UP_DIV(h->size, 2);
+
+ if ((n_size > h->min) && (realloc_heap(&h, n_size)) == 0) *hp = h;
+ }
+
/*
* We didn't end up at the last element in the heap.
* This element has to be re-inserted.
return 0;
}
-void *fr_heap_pop(fr_heap_t *hp)
+/** Remove a node from the heap
+ *
+ * @param[in,out] hp The heap to pop an element from.
+ * A new pointer value will be written to hp
+ * if the heap is resized.
+ * @return
+ * - The item that was popped.
+ * - NULL on error.
+ */
+void *fr_heap_pop(fr_heap_t **hp)
{
- fr_heap_ext_t *h = *hp;
+ fr_heap_t *h = *hp;
void *data;
*
* @note If the heap is modified the iterator should be considered invalidated.
*
- * @param[in] hp to iterate over.
+ * @param[in] h to iterate over.
* @param[in] iter Pointer to an iterator struct, used to maintain
* state between calls.
* @return
* - User data.
* - NULL if at the end of the list.
*/
-void *fr_heap_iter_init(fr_heap_t *hp, fr_heap_iter_t *iter)
+void *fr_heap_iter_init(fr_heap_t *h, fr_heap_iter_t *iter)
{
- fr_heap_ext_t *h = *hp;
-
*iter = 1;
if (h->num_elements == 0) return NULL;
*
* @note If the heap is modified the iterator should be considered invalidated.
*
- * @param[in] hp to iterate over.
+ * @param[in] h to iterate over.
* @param[in] iter Pointer to an iterator struct, used to maintain
* state between calls.
* @return
* - User data.
* - NULL if at the end of the list.
*/
-void *fr_heap_iter_next(fr_heap_t *hp, fr_heap_iter_t *iter)
+void *fr_heap_iter_next(fr_heap_t *h, fr_heap_iter_t *iter)
{
- fr_heap_ext_t *h = *hp;
-
if ((*iter + 1) > h->num_elements) return NULL;
*iter += 1;
}
#ifndef TALLOC_GET_TYPE_ABORT_NOOP
-void fr_heap_verify(char const *file, int line, fr_heap_t *hp)
+void fr_heap_verify(char const *file, int line, fr_heap_t *h)
{
- fr_heap_ext_t *h;
-
- fr_fatal_assert_msg(hp, "CONSISTENCY CHECK FAILED %s[%i]: fr_heap_t pointer was NULL", file, line);
- (void) talloc_get_type_abort(hp, fr_heap_t);
+ fr_fatal_assert_msg(h, "CONSISTENCY CHECK FAILED %s[%i]: fr_heap_t pointer was NULL", file, line);
+ (void) talloc_get_type_abort(h, fr_heap_t);
/*
* Allocating the heap structure and the array holding the heap as described in data structure
* fr_heap_t * isn't realloc()ed out from under the user, hence the following (and the use of h
* rather than hp to access anything in the heap structure).
*/
- h = *hp;
fr_fatal_assert_msg(h, "CONSISTENCY CHECK FAILED %s[%i]: heap_t pointer was NULL", file, line);
- (void) talloc_get_type_abort(h, fr_heap_ext_t);
+ (void) talloc_get_type_abort(h, fr_heap_t);
fr_fatal_assert_msg(h->num_elements <= h->size,
"CONSISTENCY CHECK FAILED %s[%i]: num_elements exceeds size", file, line);
* of the minimum element. The heap entry can contain an "int"
* field that holds the entries position in the heap. The offset
* of the field is held inside of the heap structure.
- *
- * The reason why we have fr_heap_ext_t and fr_heap_t, is that
- * fr_heap_t is a pointer to a fr_heap_ext_t. This means that
- * the heap cann be a single contiguous memory chunk, and can
- * be reallocated during extension.
*/
typedef struct {
unsigned int _CONST size; //!< Number of nodes allocated.
+ unsigned int _CONST min; //!< Minimum number of elements we allow
+ ///< the heap to reduce down to.
size_t _CONST offset; //!< Offset of heap index in element structure.
unsigned int _CONST num_elements; //!< Number of nodes used.
fr_heap_cmp_t _CONST cmp; //!< Comparator function.
void * _CONST p[]; //!< Array of nodes.
-} fr_heap_ext_t;
+} fr_heap_t;
typedef unsigned int fr_heap_index_t;
typedef unsigned int fr_heap_iter_t;
-/** How many talloc headers need to be pre-allocated for a heap
- */
-typedef fr_heap_ext_t * fr_heap_t;
-
/** How many talloc headers need to be pre-allocated for a heap
*/
#define FR_HEAP_TALLOC_HEADERS 2
/** Return the item from the top of the heap but don't pop it
*
- * @param[in] hp to return element from.
+ * @param[in] h to return element from.
* @return
* - Element at the top of the heap.
* - NULL if no elements remain in the heap.
*/
-static inline void *fr_heap_peek(fr_heap_t *hp)
+static inline void *fr_heap_peek(fr_heap_t *h)
{
- fr_heap_ext_t *h = *hp;
-
if (h->num_elements == 0) return NULL;
return h->p[1];
/** Peek at a specific index in the heap
*
- * @param[in] hp to return element from.
+ * @param[in] h to return element from.
* @param[in] idx to lookup
* @return
* - Element at the top of the heap.
* - NULL if index outside of the range of the heap.
*/
-static inline void *fr_heap_peek_at(fr_heap_t *hp, fr_heap_index_t idx)
+static inline void *fr_heap_peek_at(fr_heap_t *h, fr_heap_index_t idx)
{
- fr_heap_ext_t *h = *hp;
-
if (unlikely(idx > h->num_elements)) return NULL;
return h->p[idx];
/** Peek at the last element in the heap (not necessarily the bottom)
*
- * @param[in] hp to return element from.
+ * @param[in] h to return element from.
* @return
* - Last element in the heap.
* - NULL if no elements remain in the heap.
*/
-static inline void *fr_heap_peek_tail(fr_heap_t *hp)
+static inline void *fr_heap_peek_tail(fr_heap_t *h)
{
- fr_heap_ext_t *h = *hp;
-
if (h->num_elements == 0) return NULL;
/*
/** Return the number of elements in the heap
*
- * @param[in] hp to return the number of elements from.
+ * @param[in] h to return the number of elements from.
*/
-static inline unsigned int fr_heap_num_elements(fr_heap_t *hp)
+static inline unsigned int fr_heap_num_elements(fr_heap_t *h)
{
- fr_heap_ext_t *h = *hp;
-
return h->num_elements;
}
-int fr_heap_insert(fr_heap_t *hp, void *data) CC_HINT(nonnull);
-int fr_heap_extract(fr_heap_t *hp, void *data) CC_HINT(nonnull);
-void *fr_heap_pop(fr_heap_t *hp) CC_HINT(nonnull);
+int fr_heap_insert(fr_heap_t **hp, void *data) CC_HINT(nonnull);
+int fr_heap_extract(fr_heap_t **hp, void *data) CC_HINT(nonnull);
+void *fr_heap_pop(fr_heap_t **hp) CC_HINT(nonnull);
void *fr_heap_iter_init(fr_heap_t *hp, fr_heap_iter_t *iter) CC_HINT(nonnull);
void *fr_heap_iter_next(fr_heap_t *hp, fr_heap_iter_t *iter) CC_HINT(nonnull);
#include "heap.c"
-static bool fr_heap_check(fr_heap_t *hp, void *data)
+static bool fr_heap_check(fr_heap_t *h, void *data)
{
unsigned int i;
- fr_heap_ext_t *h = *hp;
if (!h || (h->num_elements == 0)) return false;
TEST_CASE("insertions");
for (i = 0; i < HEAP_TEST_SIZE; i++) {
FR_HEAP_VERIFY(hp);
- TEST_CHECK((ret = fr_heap_insert(hp, &array[i])) >= 0);
+ TEST_CHECK((ret = fr_heap_insert(&hp, &array[i])) >= 0);
TEST_MSG("insert failed, returned %i - %s", ret, fr_strerror());
TEST_CHECK(fr_heap_check(hp, &array[i]));
TEST_CHECK(array[entry].heap != 0);
TEST_MSG("element %i removed out of order", entry);
- TEST_CHECK((ret = fr_heap_extract(hp, &array[entry])) >= 0);
+ TEST_CHECK((ret = fr_heap_extract(&hp, &array[entry])) >= 0);
TEST_MSG("element %i removal failed, returned %i - %s", entry, ret, fr_strerror());
TEST_CHECK(!fr_heap_check(hp, &array[entry]));
TEST_CHECK((t = fr_heap_peek(hp)) != NULL);
TEST_MSG("expected %i elements remaining in the heap", left - i);
- TEST_CHECK(fr_heap_extract(hp, t) >= 0);
+ TEST_CHECK(fr_heap_extract(&hp, t) >= 0);
TEST_MSG("failed extracting %i", i);
}
TEST_CASE("insertions");
for (i = 0; i < HEAP_TEST_SIZE; i++) {
- TEST_CHECK((ret = fr_heap_insert(hp, &array[i])) >= 0);
+ TEST_CHECK((ret = fr_heap_insert(&hp, &array[i])) >= 0);
TEST_MSG("insert failed, returned %i - %s", ret, fr_strerror());
TEST_CHECK(fr_heap_check(hp, &array[i]));
TEST_CASE("ordering");
- while ((thing = fr_heap_pop(hp))) {
+ while ((thing = fr_heap_pop(&hp))) {
TEST_CHECK(thing->data >= data);
TEST_MSG("Expected data >= %i, got %i", data, thing->data);
if (thing->data >= data) data = thing->data;
for (size_t i = 0; i < HEAP_ITER_SIZE; i++) {
array[i].data = i;
- TEST_CHECK(fr_heap_insert(hp, &array[i]) >= 0);
+ TEST_CHECK(fr_heap_insert(&hp, &array[i]) >= 0);
}
data_set = 0;
start_insert = fr_time();
TEST_CASE("insertions");
for (i = 0; i < HEAP_CYCLE_SIZE; i++) {
- TEST_CHECK((ret = fr_heap_insert(hp, &array[i])) >= 0);
+ TEST_CHECK((ret = fr_heap_insert(&hp, &array[i])) >= 0);
TEST_MSG("insert failed, returned %i - %s", ret, fr_strerror());
}
TEST_CHECK(fr_heap_num_elements(hp) == HEAP_CYCLE_SIZE);
TEST_CHECK((t = fr_heap_peek(hp)) != NULL);
TEST_MSG("expected %i elements remaining in the heap", to_remove - i);
- TEST_CHECK(fr_heap_extract(hp, t) >= 0);
+ TEST_CHECK(fr_heap_extract(&hp, t) >= 0);
TEST_MSG("failed extracting %i - %s", i, fr_strerror());
}
for (i = 0; i < HEAP_CYCLE_SIZE; i++) {
if (!fr_heap_entry_inserted(array[i].heap)) {
- TEST_CHECK((ret = fr_heap_insert(hp, &array[i])) >= 0);
+ TEST_CHECK((ret = fr_heap_insert(&hp, &array[i])) >= 0);
TEST_MSG("insert failed, returned %i - %s", ret, fr_strerror());
inserted++;
} else {
- TEST_CHECK((ret = fr_heap_extract(hp, &array[i])) >= 0);
+ TEST_CHECK((ret = fr_heap_extract(&hp, &array[i])) >= 0);
TEST_MSG("element %i removal failed, returned %i - %s", i, ret, fr_strerror());
removed++;
}
for (unsigned int i = 0; i < INITIAL_CAPACITY; i++) {
TEST_CHECK((ret = fr_lst_insert(lst, &lst_array[i])) >= 0);
TEST_MSG("lst insert failed, iteration %d; returned %i - %s", i, ret, fr_strerror());
- TEST_CHECK((ret = fr_heap_insert(hp, &hp_array[i])) >= 0);
+ TEST_CHECK((ret = fr_heap_insert(&hp, &hp_array[i])) >= 0);
TEST_MSG("heap insert failed, iteration %d; returned %i - %s", i, ret, fr_strerror());
}
TEST_CASE("partial pop");
for (unsigned int i = 0; i < INITIAL_CAPACITY / 2; i++) {
TEST_CHECK((from_lst = fr_lst_pop(lst)) != NULL);
- TEST_CHECK((from_hp = fr_heap_pop(hp)) != NULL);
+ TEST_CHECK((from_hp = fr_heap_pop(&hp)) != NULL);
TEST_CHECK(lst_cmp(from_lst, from_hp) == 0);
}
for (unsigned int i = INITIAL_CAPACITY; i < 2 * INITIAL_CAPACITY; i++) {
TEST_CHECK((ret = fr_lst_insert(lst, &lst_array[i])) >= 0);
TEST_MSG("lst insert failed, iteration %u; returned %i - %s", i, ret, fr_strerror());
- TEST_CHECK((ret = fr_heap_insert(hp, &hp_array[i])) >= 0);
+ TEST_CHECK((ret = fr_heap_insert(&hp, &hp_array[i])) >= 0);
TEST_MSG("heap insert failed, iteration %u; returned %i - %s", i, ret, fr_strerror());
}
TEST_CASE("complete pop");
for (unsigned int i = 0; i < 3 * INITIAL_CAPACITY / 2; i++) {
TEST_CHECK((from_lst = fr_lst_pop(lst)) != NULL);
- TEST_CHECK((from_hp = fr_heap_pop(hp)) != NULL);
+ TEST_CHECK((from_hp = fr_heap_pop(&hp)) != NULL);
TEST_CHECK(lst_cmp(from_lst, from_hp) == 0);
}
static void queue_cmp(unsigned int count)
{
fr_lst_t *lst;
- fr_heap_t *heap;
+ fr_heap_t *hp;
lst_thing *values;
populate_values(values, count);
start_alloc = fr_time();
- heap = fr_heap_alloc(NULL, lst_cmp, lst_thing, idx, count);
+ hp = fr_heap_alloc(NULL, lst_cmp, lst_thing, idx, count);
end_alloc = fr_time();
- TEST_CHECK(heap != NULL);
+ TEST_CHECK(hp != NULL);
start_insert = fr_time();
- for (i = 0; i < count; i++) fr_heap_insert(heap, &values[i]);
+ for (i = 0; i < count; i++) fr_heap_insert(&hp, &values[i]);
end_insert = fr_time();
start_pop = fr_time();
for (i = 0; i < count; i++) {
- TEST_CHECK(fr_heap_pop(heap) != NULL);
+ TEST_CHECK(fr_heap_pop(&hp) != NULL);
if (i == 0) end_pop_first = fr_time();
TEST_MSG("expected %u elements remaining in the heap", count - i);
TEST_MSG_ALWAYS("pop-first: %"PRIu64" μs\n", fr_time_delta_unwrap(fr_time_sub(end_pop_first, start_pop)) / 1000);
TEST_MSG_ALWAYS("pop: %"PRIu64" μs\n", fr_time_delta_unwrap(fr_time_sub(end_pop, start_pop)) / 1000);
- talloc_free(heap);
+ talloc_free(hp);
}
/*
static void queue_cmp(unsigned int count)
{
fr_minmax_heap_t *minmax;
- fr_heap_t *heap;
+ fr_heap_t *hp;
minmax_heap_thing *values;
populate_values(values, count);
start_alloc = fr_time();
- heap = fr_heap_alloc(NULL, minmax_heap_cmp, minmax_heap_thing, idx, count);
+ hp = fr_heap_alloc(NULL, minmax_heap_cmp, minmax_heap_thing, idx, count);
end_alloc = fr_time();
- TEST_CHECK(heap != NULL);
+ TEST_CHECK(hp != NULL);
start_insert = fr_time();
- for (i = 0; i < count; i++) fr_heap_insert(heap, &values[i]);
+ for (i = 0; i < count; i++) fr_heap_insert(&hp, &values[i]);
end_insert = fr_time();
start_pop = fr_time();
for (i = 0; i < count; i++) {
- TEST_CHECK(fr_heap_pop(heap) != NULL);
+ TEST_CHECK(fr_heap_pop(&hp) != NULL);
if (i == 0) end_pop_first = fr_time();
TEST_MSG("expected %u elements remaining in the heap", count - i);
TEST_MSG_ALWAYS("pop-first: %"PRIu64" μs\n", fr_time_delta_to_usec(fr_time_sub(end_pop_first, start_pop)));
TEST_MSG_ALWAYS("pop: %"PRIu64" μs\n", fr_time_delta_to_usec(fr_time_sub(end_pop, start_pop)));
- talloc_free(heap);
+ talloc_free(hp);
}
/*
break;
case FR_SIGNAL_CANCEL:
-// (void) fr_heap_extract(request->backlog, request);
+// (void) fr_heap_extract(&request->backlog, request);
//request_delete(request);
break;
*/
c = fr_heap_peek(driver->heap);
if (c && (fr_unix_time_lt(c->expires, fr_time_to_unix_time(request->packet->timestamp)))) {
- fr_heap_extract(driver->heap, c);
+ fr_heap_extract(&driver->heap, c);
fr_rb_delete(driver->cache, c);
talloc_free(c);
}
c = fr_rb_find(driver->cache, &(rlm_cache_entry_t){ .key = key, .key_len = key_len });
if (!c) return CACHE_MISS;
- fr_heap_extract(driver->heap, c);
+ fr_heap_extract(&driver->heap, c);
fr_rb_delete(driver->cache, c);
talloc_free(c);
}
}
- if (fr_heap_insert(driver->heap, UNCONST(rlm_cache_entry_t *, c)) < 0) {
+ if (fr_heap_insert(&driver->heap, UNCONST(rlm_cache_entry_t *, c)) < 0) {
fr_rb_delete(driver->cache, c);
RERROR("Failed adding entry to expiry heap");
if (!request) return CACHE_ERROR;
#endif
- if (!fr_cond_assert(fr_heap_extract(driver->heap, c) == 0)) {
+ if (!fr_cond_assert(fr_heap_extract(&driver->heap, c) == 0)) {
RERROR("Entry not in heap");
return CACHE_ERROR;
}
- if (fr_heap_insert(driver->heap, c) < 0) {
+ if (fr_heap_insert(&driver->heap, c) < 0) {
fr_rb_delete(driver->cache, c); /* make sure we don't leak entries... */
RERROR("Failed updating entry TTL. Entry was forcefully expired");
return CACHE_ERROR;