I try to develop a little Postgresql shared hash extension, just to store constant values to an key. This is onetime loaded and can be accessed by any connected client.
Not really a rocket-science.
#include "postgres.h"
#include "fmgr.h"
#include "miscadmin.h"
#include "utils/builtins.h"
#include "utils/memutils.h"
#include "utils/elog.h"
#include "utils/hsearch.h"
#include "storage/shmem.h"
#include "common/hashfn.h"
PG_MODULE_MAGIC;
#define HASH_SIZE 20000
#define KEY_SIZE 128
#define VALUE_SIZE 128
static HTAB *shared_hash = NULL;
typedef struct
{
char key [ KEY_SIZE ];
char value[ VALUE_SIZE ];
} SharedHashEntry;
void _PG_init(void);
void _PG_fini(void);
PG_FUNCTION_INFO_V1(pg_config_set);
static void initialize_shared_hash(void);
static void add_shared_hash_entry(const char *key, const char *value);
static void delete_shared_hash(void);
void _PG_init(void)
{
initialize_shared_hash();
}
void _PG_fini(void)
{
delete_shared_hash();
}
Datum pg_config_set ( PG_FUNCTION_ARGS )
{
char *const_name = text_to_cstring(PG_GETARG_TEXT_PP(0));
char *const_value= text_to_cstring(PG_GETARG_TEXT_PP(1));
add_shared_hash_entry (const_name, const_value);
pfree(const_name);
pfree(const_value);
PG_RETURN_VOID();
}
static void initialize_shared_hash(void) {
HASHCTL ctl;
if (!process_shared_preload_libraries_in_progress)
return;
elog(INFO,"Start init the shmem-hash");
memset(&ctl, 0, sizeof(ctl));
ctl.keysize = sizeof(char) * KEY_SIZE;
ctl.entrysize = sizeof(SharedHashEntry);
ctl.hash = string_hash;
shared_hash = ShmemInitHash("shared_hash_char", HASH_SIZE, HASH_SIZE, &ctl, HASH_ELEM | HASH_FUNCTION);
elog(INFO,"Finished init the shmem-hash");
}
static void delete_shared_hash(void)
{
if (shared_hash != NULL)
{
hash_destroy(shared_hash);
shared_hash = NULL;
}
}
static void add_shared_hash_entry(const char *key, const char *value) {
bool found;
SharedHashEntry *entry;
entry = (SharedHashEntry *)hash_search(shared_hash, key, HASH_ENTER, &found);
if (entry == NULL)
elog(ERROR, "hash_search failed");
if (found)
elog(ERROR, "Duplicate key found in shared hash");
strcpy ( entry->key, key);
strcpy ( entry->value, value);
}
If I add the library to the shared_preload_libraries the postgres-server crashed with SEGV. If not, and I define the PLSQL-Function
CREATE FUNCTION sg_config.set(name text, conf_value text) RETURNS void
LANGUAGE C STRICT AS '/usr/lib/postgresql/15/lib/pg_config.so', 'pg_config_set';
the server signals "out of memory". I looked a bit in Github to find similar extension and I don't see, where I made the mistake.
thx Nik