#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); } }