1 /*-------------------------------------------------------------------------
4 * Simplistic testbed for shared memory and semaphore code.
6 * This file allows for quick "smoke testing" of a PG semaphore or shared
7 * memory implementation, with less overhead than compiling up a whole
8 * installation. To use:
9 * 1. Run configure, then edit src/include/pg_config.h to select the
10 * USE_xxx_SEMAPHORES and USE_xxx_SHARED_MEMORY settings you want.
11 * Also, adjust the pg_sema.c and pg_shmem.c symlinks in
12 * src/backend/port/ if needed.
13 * 2. In src/backend/port/, do "gmake ipc_test".
14 * 3. Run ipc_test and see if it works.
15 * 4. If it seems to work, try building the whole system and running
16 * the parallel regression tests for a more complete test.
19 * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
20 * Portions Copyright (c) 1994, Regents of the University of California
24 * $PostgreSQL: pgsql/src/backend/port/ipc_test.c,v 1.26 2009/01/01 17:23:46 momjian Exp $
26 *-------------------------------------------------------------------------
32 #include "miscadmin.h"
33 #include "storage/ipc.h"
34 #include "storage/pg_sema.h"
35 #include "storage/pg_shmem.h"
38 /********* stuff needed to satisfy references in shmem/sema code *********/
41 volatile bool InterruptPending = false;
42 volatile bool QueryCancelPending = false;
43 volatile bool ProcDiePending = false;
44 volatile bool ImmediateInterruptOK = false;
45 volatile uint32 InterruptHoldoffCount = 0;
46 volatile uint32 CritSectionCount = 0;
48 bool IsUnderPostmaster = false;
49 bool assert_enabled = true;
57 #define MAX_ON_EXITS 20
61 pg_on_exit_callback function;
63 } on_proc_exit_list[MAX_ON_EXITS], on_shmem_exit_list[MAX_ON_EXITS];
65 static int on_proc_exit_index,
72 while (--on_proc_exit_index >= 0)
73 (*on_proc_exit_list[on_proc_exit_index].function) (code,
74 on_proc_exit_list[on_proc_exit_index].arg);
81 while (--on_shmem_exit_index >= 0)
82 (*on_shmem_exit_list[on_shmem_exit_index].function) (code,
83 on_shmem_exit_list[on_shmem_exit_index].arg);
84 on_shmem_exit_index = 0;
88 on_shmem_exit(pg_on_exit_callback function, Datum arg)
90 if (on_shmem_exit_index >= MAX_ON_EXITS)
91 elog(FATAL, "out of on_shmem_exit slots");
93 on_shmem_exit_list[on_shmem_exit_index].function = function;
94 on_shmem_exit_list[on_shmem_exit_index].arg = arg;
96 ++on_shmem_exit_index;
102 on_shmem_exit_index = 0;
103 on_proc_exit_index = 0;
107 RecordSharedMemoryInLockFile(unsigned long id1, unsigned long id2)
112 ProcessInterrupts(void)
117 ExceptionalCondition(const char *conditionName,
118 const char *errorType,
119 const char *fileName,
122 fprintf(stderr, "TRAP: %s(\"%s\", File: \"%s\", Line: %d)\n",
123 errorType, conditionName,
124 fileName, lineNumber);
131 errcode_for_file_access(void)
137 errstart(int elevel, const char *filename, int lineno,
138 const char *funcname)
140 return (elevel >= ERROR);
144 errfinish(int dummy,...)
150 elog_start(const char *filename, int lineno, const char *funcname)
155 elog_finish(int elevel, const char *fmt,...)
157 fprintf(stderr, "ERROR: %s\n", fmt);
162 errcode(int sqlerrcode)
164 return 0; /* return value does not matter */
168 errmsg(const char *fmt,...)
170 fprintf(stderr, "ERROR: %s\n", fmt);
171 return 0; /* return value does not matter */
175 errmsg_internal(const char *fmt,...)
177 fprintf(stderr, "ERROR: %s\n", fmt);
178 return 0; /* return value does not matter */
182 errdetail(const char *fmt,...)
184 fprintf(stderr, "DETAIL: %s\n", fmt);
185 return 0; /* return value does not matter */
189 errdetail_log(const char *fmt,...)
191 fprintf(stderr, "DETAIL: %s\n", fmt);
192 return 0; /* return value does not matter */
196 errhint(const char *fmt,...)
198 fprintf(stderr, "HINT: %s\n", fmt);
199 return 0; /* return value does not matter */
203 /********* here's the actual test *********/
206 typedef struct MyStorage
208 PGShmemHeader header;
215 main(int argc, char **argv)
220 printf("Creating shared memory ... ");
223 storage = (MyStorage *) PGSharedMemoryCreate(8192, false, 5433);
225 storage->flag = 1234;
229 printf("Creating semaphores ... ");
232 PGReserveSemaphores(2, 5433);
234 PGSemaphoreCreate(&storage->sem);
238 /* sema initial value is 1, so lock should work */
240 printf("Testing Lock ... ");
243 PGSemaphoreLock(&storage->sem, false);
247 /* now sema value is 0, so trylock should fail */
249 printf("Testing TryLock ... ");
252 if (PGSemaphoreTryLock(&storage->sem))
253 printf("unexpected result!\n");
257 /* unlocking twice and then locking twice should work... */
259 printf("Testing Multiple Lock ... ");
262 PGSemaphoreUnlock(&storage->sem);
263 PGSemaphoreUnlock(&storage->sem);
265 PGSemaphoreLock(&storage->sem, false);
266 PGSemaphoreLock(&storage->sem, false);
270 /* check Reset too */
272 printf("Testing Reset ... ");
275 PGSemaphoreUnlock(&storage->sem);
277 PGSemaphoreReset(&storage->sem);
279 if (PGSemaphoreTryLock(&storage->sem))
280 printf("unexpected result!\n");
284 /* Fork a child process and see if it can communicate */
286 printf("Forking child process ... ");
296 PGSemaphoreUnlock(&storage->sem);
302 printf("failed: %s\n", strerror(errno));
306 printf("forked child pid %d OK\n", cpid);
308 if (storage->flag != 1234)
309 printf("Wrong value found in shared memory!\n");
311 printf("Waiting for child (should wait 3 sec here) ... ");
314 PGSemaphoreLock(&storage->sem, false);
318 if (storage->flag != 1235)
319 printf("Wrong value found in shared memory!\n");
323 printf("Running shmem_exit processing ... ");
330 printf("Tests complete.\n");
334 return 0; /* not reached */