OSDN Git Service

2421a7e5a026ba41d77ba9f0cf7f3ddba81aa70a
[pg-rex/syncrep.git] / src / backend / port / ipc_test.c
1 /*-------------------------------------------------------------------------
2  *
3  * ipc_test.c
4  *         Simplistic testbed for shared memory and semaphore code.
5  *
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.
17  *
18  *
19  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
20  * Portions Copyright (c) 1994, Regents of the University of California
21  *
22  *
23  * IDENTIFICATION
24  *        $Header: /cvsroot/pgsql/src/backend/port/ipc_test.c,v 1.4 2002/08/10 20:29:18 momjian Exp $
25  *
26  *-------------------------------------------------------------------------
27  */
28 #include "postgres.h"
29
30 #include <errno.h>
31 #include <unistd.h>
32
33 #include "miscadmin.h"
34 #include "storage/ipc.h"
35 #include "storage/pg_sema.h"
36 #include "storage/pg_shmem.h"
37
38
39 /********* stuff needed to satisfy references in shmem/sema code *********/
40
41
42 volatile bool InterruptPending = false;
43 volatile bool QueryCancelPending = false;
44 volatile bool ProcDiePending = false;
45 volatile bool ImmediateInterruptOK = false;
46 volatile uint32 InterruptHoldoffCount = 0;
47 volatile uint32 CritSectionCount = 0;
48
49 bool            IsUnderPostmaster = false;
50
51 int                     MaxBackends = DEF_MAXBACKENDS;
52 int                     NBuffers = DEF_NBUFFERS;
53
54 #ifndef assert_enabled
55 bool         assert_enabled = true;
56 #endif
57
58
59 #define MAX_ON_EXITS 20
60
61 static struct ONEXIT
62 {
63         void            (*function) ();
64         Datum           arg;
65 }       on_proc_exit_list[MAX_ON_EXITS], on_shmem_exit_list[MAX_ON_EXITS];
66
67 static int      on_proc_exit_index,
68                         on_shmem_exit_index;
69
70 void
71 proc_exit(int code)
72 {
73         shmem_exit(code);
74         while (--on_proc_exit_index >= 0)
75                 (*on_proc_exit_list[on_proc_exit_index].function) (code,
76                                                           on_proc_exit_list[on_proc_exit_index].arg);
77         exit(code);
78 }
79
80 void
81 shmem_exit(int code)
82 {
83         while (--on_shmem_exit_index >= 0)
84                 (*on_shmem_exit_list[on_shmem_exit_index].function) (code,
85                                                         on_shmem_exit_list[on_shmem_exit_index].arg);
86         on_shmem_exit_index = 0;
87 }
88
89 void
90 on_shmem_exit(void (*function) (), Datum arg)
91 {
92         if (on_shmem_exit_index >= MAX_ON_EXITS)
93                 elog(FATAL, "Out of on_shmem_exit slots");
94
95         on_shmem_exit_list[on_shmem_exit_index].function = function;
96         on_shmem_exit_list[on_shmem_exit_index].arg = arg;
97
98         ++on_shmem_exit_index;
99 }
100
101 void
102 on_exit_reset(void)
103 {
104         on_shmem_exit_index = 0;
105         on_proc_exit_index = 0;
106 }
107
108 void
109 RecordSharedMemoryInLockFile(unsigned long id1, unsigned long id2)
110 {
111 }
112
113 void
114 ProcessInterrupts(void)
115 {
116 }
117
118 int
119 ExceptionalCondition(char *conditionName,
120                                          char *errorType,
121                                          char *fileName,
122                                          int lineNumber)
123 {
124         fprintf(stderr, "TRAP: %s(\"%s\", File: \"%s\", Line: %d)\n",
125                         errorType, conditionName,
126                         fileName, lineNumber);
127         abort();
128         return 0;
129 }
130
131 void
132 elog(int lev, const char *fmt,...)
133 {
134         if (lev >= ERROR)
135         {
136                 fprintf(stderr, "elog(%s)\n", fmt);
137                 abort();
138         }
139 }
140
141
142 /********* here's the actual test *********/
143
144
145 typedef struct MyStorage
146 {
147         PGShmemHeader   header;
148         int                             flag;
149         PGSemaphoreData sem;
150 } MyStorage;
151
152
153 int
154 main(int argc, char **argv)
155 {
156         MyStorage          *storage;
157         int                             cpid;
158
159         printf("Creating shared memory ... ");
160         fflush(stdout);
161
162         storage = (MyStorage *) PGSharedMemoryCreate(8192, false, 5433);
163
164         storage->flag = 1234;
165
166         printf("OK\n");
167
168         printf("Creating semaphores ... ");
169         fflush(stdout);
170
171         PGReserveSemaphores(2, 5433);
172
173         PGSemaphoreCreate(&storage->sem);
174
175         printf("OK\n");
176
177         /* sema initial value is 1, so lock should work */
178
179         printf("Testing Lock ... ");
180         fflush(stdout);
181
182         PGSemaphoreLock(&storage->sem, false);
183
184         printf("OK\n");
185
186         /* now sema value is 0, so trylock should fail */
187
188         printf("Testing TryLock ... ");
189         fflush(stdout);
190
191         if (PGSemaphoreTryLock(&storage->sem))
192                 printf("unexpected result!\n");
193         else
194                 printf("OK\n");
195
196         /* unlocking twice and then locking twice should work... */
197
198         printf("Testing Multiple Lock ... ");
199         fflush(stdout);
200
201         PGSemaphoreUnlock(&storage->sem);
202         PGSemaphoreUnlock(&storage->sem);
203
204         PGSemaphoreLock(&storage->sem, false);
205         PGSemaphoreLock(&storage->sem, false);
206
207         printf("OK\n");
208
209         /* check Reset too */
210
211         printf("Testing Reset ... ");
212         fflush(stdout);
213
214         PGSemaphoreUnlock(&storage->sem);
215
216         PGSemaphoreReset(&storage->sem);
217
218         if (PGSemaphoreTryLock(&storage->sem))
219                 printf("unexpected result!\n");
220         else
221                 printf("OK\n");
222
223         /* Fork a child process and see if it can communicate */
224
225         printf("Forking child process ... ");
226         fflush(stdout);
227
228         cpid = fork();
229         if (cpid == 0)
230         {
231                 /* In child */
232                 on_exit_reset();
233                 sleep(3);
234                 storage->flag++;
235                 PGSemaphoreUnlock(&storage->sem);
236                 proc_exit(0);
237         }
238         if (cpid < 0)
239         {
240                 /* Fork failed */
241                 printf("failed: %s\n", strerror(errno));
242                 proc_exit(1);
243         }
244
245         printf("forked child pid %d OK\n", cpid);
246
247         if (storage->flag != 1234)
248                 printf("Wrong value found in shared memory!\n");
249
250         printf("Waiting for child (should wait 3 sec here) ... ");
251         fflush(stdout);
252
253         PGSemaphoreLock(&storage->sem, false);
254
255         printf("OK\n");
256
257         if (storage->flag != 1235)
258                 printf("Wrong value found in shared memory!\n");
259
260         /* Test shutdown */
261
262         printf("Running shmem_exit processing ... ");
263         fflush(stdout);
264
265         shmem_exit(0);
266
267         printf("OK\n");
268
269         printf("Tests complete.\n");
270
271         proc_exit(0);
272
273         return 0;                                       /* not reached */
274 }