Skip to content

Commit

Permalink
Make binaryheap available to frontend code.
Browse files Browse the repository at this point in the history
There are a couple of places in frontend code that could make use
of this simple binary heap implementation.  This commit makes
binaryheap usable in frontend code, much like commit 26aaf97 did
for StringInfo.  Like StringInfo, the header file is left in lib/
to reduce the likelihood of unnecessary breakage.

The frontend version of binaryheap exposes a void *-based API since
frontend code does not have access to the Datum definitions.  This
seemed like a better approach than switching all existing uses to
void * or making the Datum definitions available to frontend code.

Reviewed-by: Tom Lane, Alvaro Herrera
Discussion: https://postgr.es/m/3612876.1689443232%40sss.pgh.pa.us
  • Loading branch information
nathan-bossart committed Sep 18, 2023
1 parent f73fa5a commit 5af0263
Show file tree
Hide file tree
Showing 7 changed files with 52 additions and 20 deletions.
1 change: 0 additions & 1 deletion src/backend/lib/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ top_builddir = ../../..
include $(top_builddir)/src/Makefile.global

OBJS = \
binaryheap.o \
bipartite_match.o \
bloomfilter.o \
dshash.o \
Expand Down
1 change: 0 additions & 1 deletion src/backend/lib/meson.build
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# Copyright (c) 2022-2023, PostgreSQL Global Development Group

backend_sources += files(
'binaryheap.c',
'bipartite_match.c',
'bloomfilter.c',
'dshash.c',
Expand Down
1 change: 1 addition & 0 deletions src/common/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ LIBS += $(PTHREAD_LIBS)
OBJS_COMMON = \
archive.o \
base64.o \
binaryheap.o \
checksum_helper.o \
compression.o \
config_info.o \
Expand Down
41 changes: 30 additions & 11 deletions src/backend/lib/binaryheap.c → src/common/binaryheap.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,22 @@
* Portions Copyright (c) 2012-2023, PostgreSQL Global Development Group
*
* IDENTIFICATION
* src/backend/lib/binaryheap.c
* src/common/binaryheap.c
*
*-------------------------------------------------------------------------
*/

#ifdef FRONTEND
#include "postgres_fe.h"
#else
#include "postgres.h"
#endif

#include <math.h>

#ifdef FRONTEND
#include "common/logging.h"
#endif
#include "lib/binaryheap.h"

static void sift_down(binaryheap *heap, int node_off);
Expand All @@ -34,7 +41,7 @@ binaryheap_allocate(int capacity, binaryheap_comparator compare, void *arg)
int sz;
binaryheap *heap;

sz = offsetof(binaryheap, bh_nodes) + sizeof(Datum) * capacity;
sz = offsetof(binaryheap, bh_nodes) + sizeof(bh_node_type) * capacity;
heap = (binaryheap *) palloc(sz);
heap->bh_space = capacity;
heap->bh_compare = compare;
Expand Down Expand Up @@ -106,10 +113,16 @@ parent_offset(int i)
* afterwards.
*/
void
binaryheap_add_unordered(binaryheap *heap, Datum d)
binaryheap_add_unordered(binaryheap *heap, bh_node_type d)
{
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
}
heap->bh_has_heap_property = false;
heap->bh_nodes[heap->bh_size] = d;
heap->bh_size++;
Expand Down Expand Up @@ -138,10 +151,16 @@ binaryheap_build(binaryheap *heap)
* the heap property.
*/
void
binaryheap_add(binaryheap *heap, Datum d)
binaryheap_add(binaryheap *heap, bh_node_type d)
{
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
}
heap->bh_nodes[heap->bh_size] = d;
heap->bh_size++;
sift_up(heap, heap->bh_size - 1);
Expand All @@ -154,7 +173,7 @@ binaryheap_add(binaryheap *heap, Datum d)
* without modifying the heap. The caller must ensure that this
* routine is not used on an empty heap. Always O(1).
*/
Datum
bh_node_type
binaryheap_first(binaryheap *heap)
{
Assert(!binaryheap_empty(heap) && heap->bh_has_heap_property);
Expand All @@ -169,10 +188,10 @@ binaryheap_first(binaryheap *heap)
* that this routine is not used on an empty heap. O(log n) worst
* case.
*/
Datum
bh_node_type
binaryheap_remove_first(binaryheap *heap)
{
Datum result;
bh_node_type result;

Assert(!binaryheap_empty(heap) && heap->bh_has_heap_property);

Expand Down Expand Up @@ -204,7 +223,7 @@ binaryheap_remove_first(binaryheap *heap)
* sifting the new node down.
*/
void
binaryheap_replace_first(binaryheap *heap, Datum d)
binaryheap_replace_first(binaryheap *heap, bh_node_type d)
{
Assert(!binaryheap_empty(heap) && heap->bh_has_heap_property);

Expand All @@ -221,7 +240,7 @@ binaryheap_replace_first(binaryheap *heap, Datum d)
static void
sift_up(binaryheap *heap, int node_off)
{
Datum node_val = heap->bh_nodes[node_off];
bh_node_type node_val = heap->bh_nodes[node_off];

/*
* Within the loop, the node_off'th array entry is a "hole" that
Expand All @@ -232,7 +251,7 @@ sift_up(binaryheap *heap, int node_off)
{
int cmp;
int parent_off;
Datum parent_val;
bh_node_type parent_val;

/*
* If this node is smaller than its parent, the heap condition is
Expand Down Expand Up @@ -264,7 +283,7 @@ sift_up(binaryheap *heap, int node_off)
static void
sift_down(binaryheap *heap, int node_off)
{
Datum node_val = heap->bh_nodes[node_off];
bh_node_type node_val = heap->bh_nodes[node_off];

/*
* Within the loop, the node_off'th array entry is a "hole" that
Expand Down
1 change: 1 addition & 0 deletions src/common/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
common_sources = files(
'archive.c',
'base64.c',
'binaryheap.c',
'checksum_helper.c',
'compression.c',
'controldata_utils.c',
Expand Down
26 changes: 19 additions & 7 deletions src/include/lib/binaryheap.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,23 @@
#ifndef BINARYHEAP_H
#define BINARYHEAP_H

/*
* We provide a Datum-based API for backend code and a void *-based API for
* frontend code (since the Datum definitions are not available to frontend
* code). You should typically avoid using bh_node_type directly and instead
* use Datum or void * as appropriate.
*/
#ifdef FRONTEND
typedef void *bh_node_type;
#else
typedef Datum bh_node_type;
#endif

/*
* For a max-heap, the comparator must return <0 iff a < b, 0 iff a == b,
* and >0 iff a > b. For a min-heap, the conditions are reversed.
*/
typedef int (*binaryheap_comparator) (Datum a, Datum b, void *arg);
typedef int (*binaryheap_comparator) (bh_node_type a, bh_node_type b, void *arg);

/*
* binaryheap
Expand All @@ -34,20 +46,20 @@ typedef struct binaryheap
bool bh_has_heap_property; /* debugging cross-check */
binaryheap_comparator bh_compare;
void *bh_arg;
Datum bh_nodes[FLEXIBLE_ARRAY_MEMBER];
bh_node_type bh_nodes[FLEXIBLE_ARRAY_MEMBER];
} binaryheap;

extern binaryheap *binaryheap_allocate(int capacity,
binaryheap_comparator compare,
void *arg);
extern void binaryheap_reset(binaryheap *heap);
extern void binaryheap_free(binaryheap *heap);
extern void binaryheap_add_unordered(binaryheap *heap, Datum d);
extern void binaryheap_add_unordered(binaryheap *heap, bh_node_type d);
extern void binaryheap_build(binaryheap *heap);
extern void binaryheap_add(binaryheap *heap, Datum d);
extern Datum binaryheap_first(binaryheap *heap);
extern Datum binaryheap_remove_first(binaryheap *heap);
extern void binaryheap_replace_first(binaryheap *heap, Datum d);
extern void binaryheap_add(binaryheap *heap, bh_node_type d);
extern bh_node_type binaryheap_first(binaryheap *heap);
extern bh_node_type binaryheap_remove_first(binaryheap *heap);
extern void binaryheap_replace_first(binaryheap *heap, bh_node_type d);

#define binaryheap_empty(h) ((h)->bh_size == 0)

Expand Down
1 change: 1 addition & 0 deletions src/tools/pgindent/typedefs.list
Original file line number Diff line number Diff line change
Expand Up @@ -3198,6 +3198,7 @@ bbstreamer_tar_archiver
bbstreamer_tar_parser
bbstreamer_zstd_frame
bgworker_main_type
bh_node_type
binaryheap
binaryheap_comparator
bitmapword
Expand Down

0 comments on commit 5af0263

Please sign in to comment.