Header And Logo

PostgreSQL
| The world's most advanced open source database.

ipc_test.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * ipc_test.c
00004  *     Simplistic testbed for shared memory and semaphore code.
00005  *
00006  * This file allows for quick "smoke testing" of a PG semaphore or shared
00007  * memory implementation, with less overhead than compiling up a whole
00008  * installation.  To use:
00009  *  1. Run configure, then edit src/include/pg_config.h to select the
00010  *     USE_xxx_SEMAPHORES and USE_xxx_SHARED_MEMORY settings you want.
00011  *     Also, adjust the pg_sema.c and pg_shmem.c symlinks in
00012  *     src/backend/port/ if needed.
00013  *  2. In src/backend/port/, do "gmake ipc_test".
00014  *  3. Run ipc_test and see if it works.
00015  *  4. If it seems to work, try building the whole system and running
00016  *     the parallel regression tests for a more complete test.
00017  *
00018  *
00019  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00020  * Portions Copyright (c) 1994, Regents of the University of California
00021  *
00022  *
00023  * IDENTIFICATION
00024  *    src/backend/port/ipc_test.c
00025  *
00026  *-------------------------------------------------------------------------
00027  */
00028 #include "postgres.h"
00029 
00030 #include <unistd.h>
00031 
00032 #include "miscadmin.h"
00033 #include "storage/ipc.h"
00034 #include "storage/pg_sema.h"
00035 #include "storage/pg_shmem.h"
00036 
00037 
00038 /********* stuff needed to satisfy references in shmem/sema code *********/
00039 
00040 
00041 volatile bool InterruptPending = false;
00042 volatile bool QueryCancelPending = false;
00043 volatile bool ProcDiePending = false;
00044 volatile bool ImmediateInterruptOK = false;
00045 volatile uint32 InterruptHoldoffCount = 0;
00046 volatile uint32 CritSectionCount = 0;
00047 
00048 bool        IsUnderPostmaster = false;
00049 bool        assert_enabled = true;
00050 
00051 int         MaxBackends = 32;
00052 int         NBuffers = 64;
00053 
00054 char       *DataDir = ".";
00055 
00056 
00057 #define MAX_ON_EXITS 20
00058 
00059 static struct ONEXIT
00060 {
00061     pg_on_exit_callback function;
00062     Datum       arg;
00063 }   on_proc_exit_list[MAX_ON_EXITS], on_shmem_exit_list[MAX_ON_EXITS];
00064 
00065 static int  on_proc_exit_index,
00066             on_shmem_exit_index;
00067 
00068 void
00069 proc_exit(int code)
00070 {
00071     shmem_exit(code);
00072     while (--on_proc_exit_index >= 0)
00073         (*on_proc_exit_list[on_proc_exit_index].function) (code,
00074                                   on_proc_exit_list[on_proc_exit_index].arg);
00075     exit(code);
00076 }
00077 
00078 void
00079 shmem_exit(int code)
00080 {
00081     while (--on_shmem_exit_index >= 0)
00082         (*on_shmem_exit_list[on_shmem_exit_index].function) (code,
00083                                 on_shmem_exit_list[on_shmem_exit_index].arg);
00084     on_shmem_exit_index = 0;
00085 }
00086 
00087 void
00088 on_shmem_exit(pg_on_exit_callback function, Datum arg)
00089 {
00090     if (on_shmem_exit_index >= MAX_ON_EXITS)
00091         elog(FATAL, "out of on_shmem_exit slots");
00092 
00093     on_shmem_exit_list[on_shmem_exit_index].function = function;
00094     on_shmem_exit_list[on_shmem_exit_index].arg = arg;
00095 
00096     ++on_shmem_exit_index;
00097 }
00098 
00099 void
00100 on_exit_reset(void)
00101 {
00102     on_shmem_exit_index = 0;
00103     on_proc_exit_index = 0;
00104 }
00105 
00106 void
00107 AddToDataDirLockFile(int target_line, const char *str)
00108 {
00109 }
00110 
00111 void
00112 ProcessInterrupts(void)
00113 {
00114 }
00115 
00116 void
00117 ExceptionalCondition(const char *conditionName,
00118                      const char *errorType,
00119                      const char *fileName,
00120                      int lineNumber)
00121 {
00122     fprintf(stderr, "TRAP: %s(\"%s\", File: \"%s\", Line: %d)\n",
00123             errorType, conditionName,
00124             fileName, lineNumber);
00125     abort();
00126 }
00127 
00128 
00129 int
00130 errcode_for_file_access(void)
00131 {
00132     return 0;
00133 }
00134 
00135 bool
00136 errstart(int elevel, const char *filename, int lineno,
00137          const char *funcname, const char *domain)
00138 {
00139     return (elevel >= ERROR);
00140 }
00141 
00142 void
00143 errfinish(int dummy,...)
00144 {
00145     proc_exit(1);
00146 }
00147 
00148 void
00149 elog_start(const char *filename, int lineno, const char *funcname)
00150 {
00151 }
00152 
00153 void
00154 elog_finish(int elevel, const char *fmt,...)
00155 {
00156     fprintf(stderr, "ERROR: %s\n", fmt);
00157     proc_exit(1);
00158 }
00159 
00160 int
00161 errcode(int sqlerrcode)
00162 {
00163     return 0;                   /* return value does not matter */
00164 }
00165 
00166 int
00167 errmsg(const char *fmt,...)
00168 {
00169     fprintf(stderr, "ERROR: %s\n", fmt);
00170     return 0;                   /* return value does not matter */
00171 }
00172 
00173 int
00174 errmsg_internal(const char *fmt,...)
00175 {
00176     fprintf(stderr, "ERROR: %s\n", fmt);
00177     return 0;                   /* return value does not matter */
00178 }
00179 
00180 int
00181 errdetail(const char *fmt,...)
00182 {
00183     fprintf(stderr, "DETAIL: %s\n", fmt);
00184     return 0;                   /* return value does not matter */
00185 }
00186 
00187 int
00188 errdetail_log(const char *fmt,...)
00189 {
00190     fprintf(stderr, "DETAIL: %s\n", fmt);
00191     return 0;                   /* return value does not matter */
00192 }
00193 
00194 int
00195 errhint(const char *fmt,...)
00196 {
00197     fprintf(stderr, "HINT: %s\n", fmt);
00198     return 0;                   /* return value does not matter */
00199 }
00200 
00201 
00202 /********* here's the actual test *********/
00203 
00204 
00205 typedef struct MyStorage
00206 {
00207     PGShmemHeader header;
00208     int         flag;
00209     PGSemaphoreData sem;
00210 }   MyStorage;
00211 
00212 
00213 int
00214 main(int argc, char **argv)
00215 {
00216     MyStorage  *storage;
00217     int         cpid;
00218 
00219     printf("Creating shared memory ... ");
00220     fflush(stdout);
00221 
00222     storage = (MyStorage *) PGSharedMemoryCreate(8192, false, 5433);
00223 
00224     storage->flag = 1234;
00225 
00226     printf("OK\n");
00227 
00228     printf("Creating semaphores ... ");
00229     fflush(stdout);
00230 
00231     PGReserveSemaphores(2, 5433);
00232 
00233     PGSemaphoreCreate(&storage->sem);
00234 
00235     printf("OK\n");
00236 
00237     /* sema initial value is 1, so lock should work */
00238 
00239     printf("Testing Lock ... ");
00240     fflush(stdout);
00241 
00242     PGSemaphoreLock(&storage->sem, false);
00243 
00244     printf("OK\n");
00245 
00246     /* now sema value is 0, so trylock should fail */
00247 
00248     printf("Testing TryLock ... ");
00249     fflush(stdout);
00250 
00251     if (PGSemaphoreTryLock(&storage->sem))
00252         printf("unexpected result!\n");
00253     else
00254         printf("OK\n");
00255 
00256     /* unlocking twice and then locking twice should work... */
00257 
00258     printf("Testing Multiple Lock ... ");
00259     fflush(stdout);
00260 
00261     PGSemaphoreUnlock(&storage->sem);
00262     PGSemaphoreUnlock(&storage->sem);
00263 
00264     PGSemaphoreLock(&storage->sem, false);
00265     PGSemaphoreLock(&storage->sem, false);
00266 
00267     printf("OK\n");
00268 
00269     /* check Reset too */
00270 
00271     printf("Testing Reset ... ");
00272     fflush(stdout);
00273 
00274     PGSemaphoreUnlock(&storage->sem);
00275 
00276     PGSemaphoreReset(&storage->sem);
00277 
00278     if (PGSemaphoreTryLock(&storage->sem))
00279         printf("unexpected result!\n");
00280     else
00281         printf("OK\n");
00282 
00283     /* Fork a child process and see if it can communicate */
00284 
00285     printf("Forking child process ... ");
00286     fflush(stdout);
00287 
00288     cpid = fork();
00289     if (cpid == 0)
00290     {
00291         /* In child */
00292         on_exit_reset();
00293         sleep(3);
00294         storage->flag++;
00295         PGSemaphoreUnlock(&storage->sem);
00296         proc_exit(0);
00297     }
00298     if (cpid < 0)
00299     {
00300         /* Fork failed */
00301         printf("failed: %s\n", strerror(errno));
00302         proc_exit(1);
00303     }
00304 
00305     printf("forked child PID %d OK\n", cpid);
00306 
00307     if (storage->flag != 1234)
00308         printf("Wrong value found in shared memory!\n");
00309 
00310     printf("Waiting for child (should wait 3 sec here) ... ");
00311     fflush(stdout);
00312 
00313     PGSemaphoreLock(&storage->sem, false);
00314 
00315     printf("OK\n");
00316 
00317     if (storage->flag != 1235)
00318         printf("Wrong value found in shared memory!\n");
00319 
00320     /* Test shutdown */
00321 
00322     printf("Running shmem_exit processing ... ");
00323     fflush(stdout);
00324 
00325     shmem_exit(0);
00326 
00327     printf("OK\n");
00328 
00329     printf("Tests complete.\n");
00330 
00331     proc_exit(0);
00332 
00333     return 0;                   /* not reached */
00334 }