commit 232614a8942bd54faaf84523f0953deb15692c11 Author: James Campbell Date: Thu Apr 3 01:39:57 2025 -0400 First version diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..44c4591 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,15 @@ +ARG PG_MAJOR=15 + +FROM postgres:$PG_MAJOR-bookworm + +RUN apt update + +RUN apt install -y postgresql-server-dev-$PG_MAJOR + +RUN apt install -y build-essential + +COPY . /build + +WORKDIR /build + +RUN make && make install diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..360ee16 --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ +EXTENSION = pg_lock_hash_info +MODULES = pg_lock_hash_info +DATA = pg_lock_hash_info--1.0.sql +PG_CONFIG = pg_config + +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) diff --git a/pg_lock_hash_info--1.0.sql b/pg_lock_hash_info--1.0.sql new file mode 100644 index 0000000..ba7d9c5 --- /dev/null +++ b/pg_lock_hash_info--1.0.sql @@ -0,0 +1,8 @@ +CREATE FUNCTION pg_lock_hash_info() +RETURNS TABLE ( + hash_type CHAR, + directory INT, + bucket_hash INT, + entries INT, + free_slots INT +) AS 'pg_lock_hash_info' LANGUAGE C STRICT; diff --git a/pg_lock_hash_info.c b/pg_lock_hash_info.c new file mode 100644 index 0000000..c0f8140 --- /dev/null +++ b/pg_lock_hash_info.c @@ -0,0 +1,73 @@ +#include "postgres.h" +#include "fmgr.h" +#include "access/htup_details.h" +#include "funcapi.h" +#include "storage/lwlock.h" +#include "storage/shmem.h" +#include "utils/builtins.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(pg_lock_hash_info); + +typedef struct { + int bucket_idx; + char hash_type; + int directory; + int entries; + int free_slots; +} LockHashEntry; + +Datum +pg_lock_hash_info(PG_FUNCTION_ARGS) +{ + FuncCallContext *funcctx; + LockHashEntry *entries; + + if (SRF_IS_FIRSTCALL()) + { + TupleDesc tupdesc; + MemoryContext oldcontext; + + funcctx = SRF_FIRSTCALL_INIT(); + oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); + + tupdesc = CreateTemplateTupleDesc(5); + TupleDescInitEntry(tupdesc, (AttrNumber) 1, "hash_type", TEXTOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 2, "directory", INT4OID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 3, "bucket_hash", INT4OID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 4, "entries", INT4OID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 5, "free_slots", INT4OID, -1, 0); + funcctx->tuple_desc = BlessTupleDesc(tupdesc); + + /* Allocate space for results (this should fetch real data) */ + entries = palloc(sizeof(LockHashEntry) * 10); /* Placeholder for real count */ + funcctx->user_fctx = entries; + MemoryContextSwitchTo(oldcontext); + } + + funcctx = SRF_PERCALL_SETUP(); + entries = (LockHashEntry *) funcctx->user_fctx; + + /* Placeholder loop to return mock data */ + if (funcctx->call_cntr < 10) + { + Datum values[5]; + bool nulls[5] = {false, false, false, false, false}; + HeapTuple tuple; + + values[0] = CharGetDatum(funcctx->call_cntr % 2 == 0 ? 'l' : 'p'); + values[1] = Int32GetDatum(funcctx->call_cntr / 5); + values[2] = Int32GetDatum(funcctx->call_cntr); + values[3] = Int32GetDatum(5); /* Fake number of entries */ + values[4] = Int32GetDatum(10); /* Fake number of free slots */ + + tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls); + SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple)); + } + else + { + SRF_RETURN_DONE(funcctx); + } +} + diff --git a/pg_lock_hash_info.control b/pg_lock_hash_info.control new file mode 100644 index 0000000..dacb8eb --- /dev/null +++ b/pg_lock_hash_info.control @@ -0,0 +1,3 @@ +default_version = '1.0' +comment = 'Expose lock and proclock hash bucket statistics' +relocatable = false