0

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

Nik
  • 53
  • 1
  • 9

0 Answers0