Extending SQL with C, shared library problem - Mailing list pgsql-novice

From Shawn Garbett
Subject Extending SQL with C, shared library problem
Date
Msg-id 20050720203049.82792.qmail@web54404.mail.yahoo.com
Whole thread Raw
Responses Re: Extending SQL with C, shared library problem
List pgsql-novice
I've got C code written to store a value in the
context of an active connection using a hash. It
worked until I added some semaphores to control memory
reads/writes to the shared resource. This is on SLES9
Linux box running a 2.6.5 kernel.

Here's the error from psql:
mydatabase=# select * from get_auth_party();
ERROR:  could not load library
"/usr/local/lib/audit.so": /usr/local/lib/audit.so:
undefined symbol: sem_wait

Here's what ldd reports:
straycat:/home/spgarbet/audit # ldd audit.so
        linux-gate.so.1 =>  (0xffffe000)
        libc.so.6 => /lib/tls/libc.so.6 (0x40011000)
        /lib/ld-linux.so.2 => /lib/ld-linux.so.2
(0x80000000)

Any ideas about what's wrong. sem_wait is in the
linux-gate.so.1, which is a "ghost" library provided
by the kernel. For some reason it's not linking into
that. Any suggestions?

Here's the code (The code is now in the public domain,
do with as you see fit...):

audit.c
------------------------------------------------

#include <string.h>
#include <sys/fcntl.h>
#include <semaphore.h>
#include <postgres.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>

/*
 Use `pg_config --includedir-server` to find out where
the PostgreSQL
 server header files are installed on your system

>cc -fpic -I`pg_config --includedir-server` -c audit.c
>cc -shared -o audit.so audit.o

*/

/* Postgres extension

CREATE FUNCTION get_auth_party() returns integer
  AS '/usr/local/lib/audit', 'get_auth_party'
  LANGUAGE C STRICT;

CREATE FUNCTION set_auth_party(integer) returns
integer
  AS '/usr/local/lib/audit', 'set_auth_party'
  LANGUAGE C STRICT;

*/


#define HASH_SIZE (1000)

/* Store the party_id local to the PID, which is
unique to active connections */
typedef struct hash_bin_s
{
  int32              pid;
  int32              party_id;
  struct hash_bin_s* next;
} hash_bin;

/* The initial hash is null */
hash_bin* hash=0;
sem_t*    semaphore=0;

/* Initialize the semaphore */
void init_semaphore()
{
  semaphore = sem_open("/tmp/postgres-syscontext",
O_CREAT, 644, 0);
  sem_post(semaphore);
}

/* Initialize the hash */
void init_hash()
{
  hash = (hash_bin*)malloc(sizeof(struct
hash_bin_s)*HASH_SIZE);
  memset(hash, 0, sizeof(struct
hash_bin_s)*HASH_SIZE);
}

/* Insert an entry into the hash */
void insert_into_hash(int32 party_id)
{
  hash_bin* bucket;
  int32     pid;

  if (hash == 0) { init_hash(); }

  pid = getpid();

  /* Locate bucket if it already exists */
  bucket = &(hash[pid % HASH_SIZE]);
  while(bucket->pid != pid && bucket->next != 0)
  {
    bucket = bucket->next;
  }

  /* If the current bucket has no pid -- initial
case*/
  if(bucket->pid == 0)
  {
    bucket->pid      = pid;
    bucket->party_id = party_id;
    bucket->next     = 0;
  }
  /* If the bucket is defined for this pid */
  else if(bucket->pid == pid)
  {
    bucket->party_id = party_id;
  }
  /* Due to above loop at the end of a chain, add new
entry */
  else
  {
    bucket->next = (hash_bin*)malloc(sizeof(struct
hash_bin_s));
    bucket = bucket->next;
    bucket->pid = pid;
    bucket->party_id = party_id;
    bucket->next     = 0;
  }
}

/* Get a value from the hash, 0 if not found */
int32 value_in_hash()
{
  hash_bin* bucket;
  int32     pid;

  if (hash == 0) { init_hash(); return 0; }

  pid = getpid();
  bucket = &(hash[pid % HASH_SIZE]);

  while(bucket->pid != pid && bucket->next != 0)
  {
    bucket = bucket->next;
  }

  if(bucket->pid == pid)
  {
    return bucket->party_id;
  }

  return 0;
}

/* These are the exported system context functions */
/* The hash is protected by a semaphore for access */
int32 get_auth_party()
{
  int32 val;

  if(semaphore==0) {init_semaphore();}

  val = 0;

  if(!sem_wait(semaphore))
  {
    val =  value_in_hash();
    sem_post(semaphore);
  }

  return val;
}

int32 set_auth_party(int32 party_id)
{
  if(semaphore==0) {init_semaphore();}

  if(!sem_wait(semaphore))
  {
    insert_into_hash(party_id);
    sem_post(semaphore);
  }

  return party_id;
}




____________________________________________________
Start your day with Yahoo! - make it your home page
http://www.yahoo.com/r/hs


pgsql-novice by date:

Previous
From: Tom Lane
Date:
Subject: Re: duplicate key violates unique constraint. (repost)
Next
From: Tom Lane
Date:
Subject: Re: Extending SQL with C, shared library problem