Logo Search packages:      
Sourcecode: postgresql-8.4 version File versions  Download package

ipc_test.c

/*-------------------------------------------------------------------------
 *
 * ipc_test.c
 *       Simplistic testbed for shared memory and semaphore code.
 *
 * This file allows for quick "smoke testing" of a PG semaphore or shared
 * memory implementation, with less overhead than compiling up a whole
 * installation.  To use:
 *    1. Run configure, then edit src/include/pg_config.h to select the
 *       USE_xxx_SEMAPHORES and USE_xxx_SHARED_MEMORY settings you want.
 *       Also, adjust the pg_sema.c and pg_shmem.c symlinks in
 *       src/backend/port/ if needed.
 *    2. In src/backend/port/, do "gmake ipc_test".
 *    3. Run ipc_test and see if it works.
 *    4. If it seems to work, try building the whole system and running
 *       the parallel regression tests for a more complete test.
 *
 *
 * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
 *      $PostgreSQL: pgsql/src/backend/port/ipc_test.c,v 1.26 2009/01/01 17:23:46 momjian Exp $
 *
 *-------------------------------------------------------------------------
 */
#include "postgres.h"

#include <unistd.h>

#include "miscadmin.h"
#include "storage/ipc.h"
#include "storage/pg_sema.h"
#include "storage/pg_shmem.h"


/********* stuff needed to satisfy references in shmem/sema code *********/


volatile bool InterruptPending = false;
volatile bool QueryCancelPending = false;
volatile bool ProcDiePending = false;
volatile bool ImmediateInterruptOK = false;
volatile uint32 InterruptHoldoffCount = 0;
volatile uint32 CritSectionCount = 0;

bool        IsUnderPostmaster = false;
bool        assert_enabled = true;

int               MaxBackends = 32;
int               NBuffers = 64;

char     *DataDir = ".";


#define MAX_ON_EXITS 20

static struct ONEXIT
{
      pg_on_exit_callback function;
      Datum       arg;
}     on_proc_exit_list[MAX_ON_EXITS], on_shmem_exit_list[MAX_ON_EXITS];

static int  on_proc_exit_index,
                  on_shmem_exit_index;

void
proc_exit(int code)
{
      shmem_exit(code);
      while (--on_proc_exit_index >= 0)
            (*on_proc_exit_list[on_proc_exit_index].function) (code,
                                                  on_proc_exit_list[on_proc_exit_index].arg);
      exit(code);
}

void
shmem_exit(int code)
{
      while (--on_shmem_exit_index >= 0)
            (*on_shmem_exit_list[on_shmem_exit_index].function) (code,
                                                on_shmem_exit_list[on_shmem_exit_index].arg);
      on_shmem_exit_index = 0;
}

void
on_shmem_exit(pg_on_exit_callback function, Datum arg)
{
      if (on_shmem_exit_index >= MAX_ON_EXITS)
            elog(FATAL, "out of on_shmem_exit slots");

      on_shmem_exit_list[on_shmem_exit_index].function = function;
      on_shmem_exit_list[on_shmem_exit_index].arg = arg;

      ++on_shmem_exit_index;
}

void
on_exit_reset(void)
{
      on_shmem_exit_index = 0;
      on_proc_exit_index = 0;
}

void
RecordSharedMemoryInLockFile(unsigned long id1, unsigned long id2)
{
}

void
ProcessInterrupts(void)
{
}

int
ExceptionalCondition(const char *conditionName,
                               const char *errorType,
                               const char *fileName,
                               int lineNumber)
{
      fprintf(stderr, "TRAP: %s(\"%s\", File: \"%s\", Line: %d)\n",
                  errorType, conditionName,
                  fileName, lineNumber);
      abort();
      return 0;
}


int
errcode_for_file_access(void)
{
      return 0;
}

bool
errstart(int elevel, const char *filename, int lineno,
             const char *funcname)
{
      return (elevel >= ERROR);
}

void
errfinish(int dummy,...)
{
      proc_exit(1);
}

void
elog_start(const char *filename, int lineno, const char *funcname)
{
}

void
elog_finish(int elevel, const char *fmt,...)
{
      fprintf(stderr, "ERROR: %s\n", fmt);
      proc_exit(1);
}

int
errcode(int sqlerrcode)
{
      return 0;                           /* return value does not matter */
}

int
errmsg(const char *fmt,...)
{
      fprintf(stderr, "ERROR: %s\n", fmt);
      return 0;                           /* return value does not matter */
}

int
errmsg_internal(const char *fmt,...)
{
      fprintf(stderr, "ERROR: %s\n", fmt);
      return 0;                           /* return value does not matter */
}

int
errdetail(const char *fmt,...)
{
      fprintf(stderr, "DETAIL: %s\n", fmt);
      return 0;                           /* return value does not matter */
}

int
errdetail_log(const char *fmt,...)
{
      fprintf(stderr, "DETAIL: %s\n", fmt);
      return 0;                           /* return value does not matter */
}

int
errhint(const char *fmt,...)
{
      fprintf(stderr, "HINT: %s\n", fmt);
      return 0;                           /* return value does not matter */
}


/********* here's the actual test *********/


typedef struct MyStorage
{
      PGShmemHeader header;
      int               flag;
      PGSemaphoreData sem;
}     MyStorage;


int
main(int argc, char **argv)
{
      MyStorage  *storage;
      int               cpid;

      printf("Creating shared memory ... ");
      fflush(stdout);

      storage = (MyStorage *) PGSharedMemoryCreate(8192, false, 5433);

      storage->flag = 1234;

      printf("OK\n");

      printf("Creating semaphores ... ");
      fflush(stdout);

      PGReserveSemaphores(2, 5433);

      PGSemaphoreCreate(&storage->sem);

      printf("OK\n");

      /* sema initial value is 1, so lock should work */

      printf("Testing Lock ... ");
      fflush(stdout);

      PGSemaphoreLock(&storage->sem, false);

      printf("OK\n");

      /* now sema value is 0, so trylock should fail */

      printf("Testing TryLock ... ");
      fflush(stdout);

      if (PGSemaphoreTryLock(&storage->sem))
            printf("unexpected result!\n");
      else
            printf("OK\n");

      /* unlocking twice and then locking twice should work... */

      printf("Testing Multiple Lock ... ");
      fflush(stdout);

      PGSemaphoreUnlock(&storage->sem);
      PGSemaphoreUnlock(&storage->sem);

      PGSemaphoreLock(&storage->sem, false);
      PGSemaphoreLock(&storage->sem, false);

      printf("OK\n");

      /* check Reset too */

      printf("Testing Reset ... ");
      fflush(stdout);

      PGSemaphoreUnlock(&storage->sem);

      PGSemaphoreReset(&storage->sem);

      if (PGSemaphoreTryLock(&storage->sem))
            printf("unexpected result!\n");
      else
            printf("OK\n");

      /* Fork a child process and see if it can communicate */

      printf("Forking child process ... ");
      fflush(stdout);

      cpid = fork();
      if (cpid == 0)
      {
            /* In child */
            on_exit_reset();
            sleep(3);
            storage->flag++;
            PGSemaphoreUnlock(&storage->sem);
            proc_exit(0);
      }
      if (cpid < 0)
      {
            /* Fork failed */
            printf("failed: %s\n", strerror(errno));
            proc_exit(1);
      }

      printf("forked child pid %d OK\n", cpid);

      if (storage->flag != 1234)
            printf("Wrong value found in shared memory!\n");

      printf("Waiting for child (should wait 3 sec here) ... ");
      fflush(stdout);

      PGSemaphoreLock(&storage->sem, false);

      printf("OK\n");

      if (storage->flag != 1235)
            printf("Wrong value found in shared memory!\n");

      /* Test shutdown */

      printf("Running shmem_exit processing ... ");
      fflush(stdout);

      shmem_exit(0);

      printf("OK\n");

      printf("Tests complete.\n");

      proc_exit(0);

      return 0;                           /* not reached */
}

Generated by  Doxygen 1.6.0   Back to index