From 00afd765c232bd00484316b497e921a9947cd1d3 Mon Sep 17 00:00:00 2001
From: Masahiko Sawada <sawada.mshk@gmail.com>
Date: Fri, 26 Jan 2024 17:12:20 +0900
Subject: [PATCH v9 1/3] Make binaryheap enlargeable.

The node array space of the binaryheap is doubled when there is no
available space.

Reviewed-by: Hayato Kuroda, Vignesh C, Ajin Cherian, Tomas Vondra,
Shubham Khanna, Peter Smith
Discussion: https://postgr.es/m/CAD21AoDffo37RC-eUuyHJKVEr017V2YYDLyn1xF_00ofptWbkg%40mail.gmail.com
---
 src/common/binaryheap.c      | 37 +++++++++++++++++++-----------------
 src/include/lib/binaryheap.h |  2 +-
 2 files changed, 21 insertions(+), 18 deletions(-)

diff --git a/src/common/binaryheap.c b/src/common/binaryheap.c
index 7377ebdf15..843e764bb6 100644
--- a/src/common/binaryheap.c
+++ b/src/common/binaryheap.c
@@ -38,17 +38,16 @@ static void sift_up(binaryheap *heap, int node_off);
 binaryheap *
 binaryheap_allocate(int capacity, binaryheap_comparator compare, void *arg)
 {
-	int			sz;
 	binaryheap *heap;
 
-	sz = offsetof(binaryheap, bh_nodes) + sizeof(bh_node_type) * capacity;
-	heap = (binaryheap *) palloc(sz);
+	heap = (binaryheap *) palloc(sizeof(binaryheap));
 	heap->bh_space = capacity;
 	heap->bh_compare = compare;
 	heap->bh_arg = arg;
 
 	heap->bh_size = 0;
 	heap->bh_has_heap_property = true;
+	heap->bh_nodes = (bh_node_type *) palloc(sizeof(bh_node_type) * capacity);
 
 	return heap;
 }
@@ -74,6 +73,7 @@ binaryheap_reset(binaryheap *heap)
 void
 binaryheap_free(binaryheap *heap)
 {
+	pfree(heap->bh_nodes);
 	pfree(heap);
 }
 
@@ -104,6 +104,17 @@ parent_offset(int i)
 	return (i - 1) / 2;
 }
 
+/*
+ * Double the space allocated for nodes.
+ */
+static void
+enlarge_node_array(binaryheap *heap)
+{
+	heap->bh_space *= 2;
+	heap->bh_nodes = repalloc(heap->bh_nodes,
+							  sizeof(bh_node_type) * heap->bh_space);
+}
+
 /*
  * binaryheap_add_unordered
  *
@@ -115,14 +126,10 @@ parent_offset(int i)
 void
 binaryheap_add_unordered(binaryheap *heap, bh_node_type d)
 {
+	/* make sure enough space for a new node */
 	if (heap->bh_size >= heap->bh_space)
-	{
-#ifdef FRONTEND
-		pg_fatal("out of binary heap slots");
-#else
-		elog(ERROR, "out of binary heap slots");
-#endif
-	}
+		enlarge_node_array(heap);
+
 	heap->bh_has_heap_property = false;
 	heap->bh_nodes[heap->bh_size] = d;
 	heap->bh_size++;
@@ -153,14 +160,10 @@ binaryheap_build(binaryheap *heap)
 void
 binaryheap_add(binaryheap *heap, bh_node_type d)
 {
+	/* make sure enough space for a new node */
 	if (heap->bh_size >= heap->bh_space)
-	{
-#ifdef FRONTEND
-		pg_fatal("out of binary heap slots");
-#else
-		elog(ERROR, "out of binary heap slots");
-#endif
-	}
+		enlarge_node_array(heap);
+
 	heap->bh_nodes[heap->bh_size] = d;
 	heap->bh_size++;
 	sift_up(heap, heap->bh_size - 1);
diff --git a/src/include/lib/binaryheap.h b/src/include/lib/binaryheap.h
index 19025c08ef..1439f20803 100644
--- a/src/include/lib/binaryheap.h
+++ b/src/include/lib/binaryheap.h
@@ -46,7 +46,7 @@ typedef struct binaryheap
 	bool		bh_has_heap_property;	/* debugging cross-check */
 	binaryheap_comparator bh_compare;
 	void	   *bh_arg;
-	bh_node_type bh_nodes[FLEXIBLE_ARRAY_MEMBER];
+	bh_node_type *bh_nodes;
 } binaryheap;
 
 extern binaryheap *binaryheap_allocate(int capacity,
-- 
2.39.3

