avoid failing hard if 'gnunetcheck' db does not exist
[oweals/gnunet.git] / src / util / container_heap.c
index c1d478e06a018ee4f7812329c92830237bb9b601..d5dca20ef70d51466b00e5d83157330bba2104dd 100644 (file)
@@ -1,21 +1,21 @@
 /*
   This file is part of GNUnet.
-  (C) 2008, 2009 Christian Grothoff (and other contributing authors)
-  
-  GNUnet 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, or (at your
-  option) any later version.
-  
+  Copyright (C) 2008, 2009 GNUnet e.V.
+
+  GNUnet is free software: you can redistribute it and/or modify it
+  under the terms of the GNU Affero General Public License as published
+  by the Free Software Foundation, either version 3 of the License,
+  or (at your option) any later version.
+
   GNUnet 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 GNUnet; see the file COPYING.  If not, write to the
-  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-  Boston, MA 02111-1307, USA.
+  Affero General Public License for more details.
+  You should have received a copy of the GNU Affero General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
 */
 
 /**
  */
 
 #include "platform.h"
-#include "gnunet_util_lib.h"
+#include "gnunet_container_lib.h"
 
+#define LOG(kind,...) GNUNET_log_from (kind, "util-container-heap", __VA_ARGS__)
 
-#define DEBUG 0
+#define EXTRA_CHECKS 0
 
 /**
  * Node in the heap.
@@ -103,7 +104,7 @@ struct GNUNET_CONTAINER_Heap
 };
 
 
-#if DEBUG
+#if EXTRA_CHECKS
 /**
  * Check if internal invariants hold for the given node.
  *
@@ -141,7 +142,7 @@ GNUNET_CONTAINER_heap_create (enum GNUNET_CONTAINER_HeapOrder order)
 {
   struct GNUNET_CONTAINER_Heap *heap;
 
-  heap = GNUNET_malloc (sizeof (struct GNUNET_CONTAINER_Heap));
+  heap = GNUNET_new (struct GNUNET_CONTAINER_Heap);
   heap->order = order;
   return heap;
 }
@@ -162,10 +163,10 @@ GNUNET_CONTAINER_heap_destroy (struct GNUNET_CONTAINER_Heap *heap)
 
 
 /**
- * Get element stored at root of heap.
+ * Get element stored at the root of @a heap.
  *
- * @param heap heap to inspect
- * @return NULL if heap is empty
+ * @param heap  Heap to inspect.
+ * @return Element at the root, or NULL if heap is empty.
  */
 void *
 GNUNET_CONTAINER_heap_peek (const struct GNUNET_CONTAINER_Heap *heap)
@@ -176,6 +177,30 @@ GNUNET_CONTAINER_heap_peek (const struct GNUNET_CONTAINER_Heap *heap)
 }
 
 
+/**
+ * Get @a element and @a cost stored at the root of @a heap.
+ *
+ * @param[in]  heap     Heap to inspect.
+ * @param[out] element  Root element is returned here.
+ * @param[out] cost     Cost of @a element is returned here.
+ * @return #GNUNET_YES if an element is returned,
+ *         #GNUNET_NO  if the heap is empty.
+ */
+int
+GNUNET_CONTAINER_heap_peek2 (const struct GNUNET_CONTAINER_Heap *heap,
+                             void **element,
+                             GNUNET_CONTAINER_HeapCostType *cost)
+{
+  if (NULL == heap->root)
+    return GNUNET_NO;
+  if (NULL != element)
+    *element = heap->root->element;
+  if (NULL != cost)
+    *cost = heap->root->cost;
+  return GNUNET_YES;
+}
+
+
 /**
  * Get the current size of the heap
  *
@@ -202,6 +227,7 @@ GNUNET_CONTAINER_heap_node_get_cost (const struct GNUNET_CONTAINER_HeapNode
   return node->cost;
 }
 
+
 /**
  * Iterate over the children of the given node.
  *
@@ -218,11 +244,11 @@ node_iterator (const struct GNUNET_CONTAINER_Heap *heap,
 {
   if (node == NULL)
     return GNUNET_YES;
-  if (GNUNET_YES != node_iterator (heap,
-                                   node->left_child, iterator, iterator_cls))
+  if (GNUNET_YES !=
+      node_iterator (heap, node->left_child, iterator, iterator_cls))
     return GNUNET_NO;
-  if (GNUNET_YES != node_iterator (heap,
-                                   node->right_child, iterator, iterator_cls))
+  if (GNUNET_YES !=
+      node_iterator (heap, node->right_child, iterator, iterator_cls))
     return GNUNET_NO;
   return iterator (iterator_cls, node, node->element, node->cost);
 }
@@ -267,9 +293,10 @@ GNUNET_CONTAINER_heap_walk_get_next (struct GNUNET_CONTAINER_Heap *heap)
   if (pos == NULL)
     pos = heap->root;
   element = pos->element;
-  heap->walk_pos
-      = (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 2))
-      ? pos->right_child : pos->left_child;
+  heap->walk_pos =
+      (0 ==
+       GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
+                                 2)) ? pos->right_child : pos->left_child;
   return element;
 }
 
@@ -290,8 +317,9 @@ insert_node (struct GNUNET_CONTAINER_Heap *heap,
   struct GNUNET_CONTAINER_HeapNode *parent;
 
   GNUNET_assert (node->parent == NULL);
-  while ((heap->order == GNUNET_CONTAINER_HEAP_ORDER_MAX)
-         ? (pos->cost >= node->cost) : (pos->cost <= node->cost))
+  while ((heap->order == GNUNET_CONTAINER_HEAP_ORDER_MAX) ? (pos->cost >=
+                                                             node->cost)
+         : (pos->cost <= node->cost))
   {
     /* node is descendent of pos */
     pos->tree_size += (1 + node->tree_size);
@@ -343,12 +371,12 @@ insert_node (struct GNUNET_CONTAINER_Heap *heap,
  * @return node for the new element
  */
 struct GNUNET_CONTAINER_HeapNode *
-GNUNET_CONTAINER_heap_insert (struct GNUNET_CONTAINER_Heap *heap,
-                              void *element, GNUNET_CONTAINER_HeapCostType cost)
+GNUNET_CONTAINER_heap_insert (struct GNUNET_CONTAINER_Heap *heap, void *element,
+                              GNUNET_CONTAINER_HeapCostType cost)
 {
   struct GNUNET_CONTAINER_HeapNode *node;
 
-  node = GNUNET_malloc (sizeof (struct GNUNET_CONTAINER_HeapNode));
+  node = GNUNET_new (struct GNUNET_CONTAINER_HeapNode);
   node->heap = heap;
   node->element = element;
   node->cost = cost;
@@ -397,10 +425,11 @@ GNUNET_CONTAINER_heap_remove_root (struct GNUNET_CONTAINER_Heap *heap)
     heap->root = root->left_child;
     insert_node (heap, heap->root, root->right_child);
   }
+  if (heap->walk_pos == root)
+    heap->walk_pos = heap->root;
   GNUNET_free (root);
-#if DEBUG
-  GNUNET_assert (((heap->size == 0) &&
-                  (heap->root == NULL)) ||
+#if EXTRA_CHECKS
+  GNUNET_assert (((heap->size == 0) && (heap->root == NULL)) ||
                  (heap->size == heap->root->tree_size + 1));
   CHECK (heap->root);
 #endif
@@ -480,7 +509,7 @@ remove_node (struct GNUNET_CONTAINER_HeapNode *node)
 
 /**
  * Removes a node from the heap.
- * 
+ *
  * @param node node to remove
  * @return element data stored at the node
  */
@@ -500,10 +529,9 @@ GNUNET_CONTAINER_heap_remove_node (struct GNUNET_CONTAINER_HeapNode *node)
   if (heap->walk_pos == node)
     heap->walk_pos = NULL;
   GNUNET_free (node);
-#if DEBUG
+#if EXTRA_CHECKS
   CHECK (heap->root);
-  GNUNET_assert (((heap->size == 0) &&
-                  (heap->root == NULL)) ||
+  GNUNET_assert (((heap->size == 0) && (heap->root == NULL)) ||
                  (heap->size == heap->root->tree_size + 1));
 #endif
   return ret;
@@ -513,39 +541,23 @@ GNUNET_CONTAINER_heap_remove_node (struct GNUNET_CONTAINER_HeapNode *node)
 /**
  * Updates the cost of any node in the tree
  *
- * @param heap heap to modify
  * @param node node for which the cost is to be changed
  * @param new_cost new cost for the node
  */
 void
-GNUNET_CONTAINER_heap_update_cost (struct GNUNET_CONTAINER_Heap *heap,
-                                   struct GNUNET_CONTAINER_HeapNode *node,
+GNUNET_CONTAINER_heap_update_cost (struct GNUNET_CONTAINER_HeapNode *node,
                                    GNUNET_CONTAINER_HeapCostType new_cost)
 {
-#if DEBUG
-  GNUNET_assert (((heap->size == 0) &&
-                  (heap->root == NULL)) ||
-                 (heap->size == heap->root->tree_size + 1));
-  CHECK (heap->root);
-#endif
+  struct GNUNET_CONTAINER_Heap *heap = node->heap;
+
   remove_node (node);
-#if DEBUG
-  CHECK (heap->root);
-  GNUNET_assert (((heap->size == 1) &&
-                  (heap->root == NULL)) ||
-                 (heap->size == heap->root->tree_size + 2));
-#endif
   node->cost = new_cost;
-  if (heap->root == NULL)
+  if (NULL == heap->root)
     heap->root = node;
   else
-    insert_node (heap, heap->root, node);
-#if DEBUG
-  CHECK (heap->root);
-  GNUNET_assert (((heap->size == 0) &&
-                  (heap->root == NULL)) ||
-                 (heap->size == heap->root->tree_size + 1));
-#endif
+    insert_node (heap,
+                 heap->root,
+                 node);
 }