OSDN Git Service

Update copyright for 2009.
[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-2009, PostgreSQL Global Development Group
20  * Portions Copyright (c) 1994, Regents of the University of California
21  *
22  *
23  * IDENTIFICATION
24  *        $PostgreSQL: pgsql/src/backend/port/ipc_test.c,v 1.26 2009/01/01 17:23:46 momjian Exp $
25  *
26  *-------------------------------------------------------------------------
27  */
28 #include "postgres.h"
29
30 #include <unistd.h>
31
32 #include "miscadmin.h"
33 #include "storage/ipc.h"
34 #include "storage/pg_sema.h"
35 #include "storage/pg_shmem.h"
36
37
38 /********* stuff needed to satisfy references in shmem/sema code *********/
39
40
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;
47
48 bool            IsUnderPostmaster = false;
49 bool            assert_enabled = true;
50
51 int                     MaxBackends = 32;
52 int                     NBuffers = 64;
53
54 char       *DataDir = ".";
55
56
57 #define MAX_ON_EXITS 20
58
59 static struct ONEXIT
60 {
61         pg_on_exit_callback function;
62         Datum           arg;
63 }       on_proc_exit_list[MAX_ON_EXITS], on_shmem_exit_list[MAX_ON_EXITS];
64
65 static int      on_proc_exit_index,
66                         on_shmem_exit_index;
67
68 void
69 proc_exit(int code)
70 {
71         shmem_exit(code);
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);
75         exit(code);
76 }
77
78 void
79 shmem_exit(int code)
80 {
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;
85 }
86
87 void
88 on_shmem_exit(pg_on_exit_callback function, Datum arg)
89 {
90         if (on_shmem_exit_index >= MAX_ON_EXITS)
91                 elog(FATAL, "out of on_shmem_exit slots");
92
93         on_shmem_exit_list[on_shmem_exit_index].function = function;
94         on_shmem_exit_list[on_shmem_exit_index].arg = arg;
95
96         ++on_shmem_exit_index;
97 }
98
99 void
100 on_exit_reset(void)
101 {
102         on_shmem_exit_index = 0;
103         on_proc_exit_index = 0;
104 }
105
106 void
107 RecordSharedMemoryInLockFile(unsigned long id1, unsigned long id2)
108 {
109 }
110
111 void
112 ProcessInterrupts(void)
113 {
114 }
115
116 int
117 ExceptionalCondition(const char *conditionName,
118                                          const char *errorType,
119                                          const char *fileName,
120                                          int lineNumber)
121 {
122         fprintf(stderr, "TRAP: %s(\"%s\", File: \"%s\", Line: %d)\n",
123                         errorType, conditionName,
124                         fileName, lineNumber);
125         abort();
126         return 0;
127 }
128
129
130 int
131 errcode_for_file_access(void)
132 {
133         return 0;
134 }
135
136 bool
137 errstart(int elevel, const char *filename, int lineno,
138                  const char *funcname)
139 {
140         return (elevel >= ERROR);
141 }
142
143 void
144 errfinish(int dummy,...)
145 {
146         proc_exit(1);
147 }
148
149 void
150 elog_start(const char *filename, int lineno, const char *funcname)
151 {
152 }
153
154 void
155 elog_finish(int elevel, const char *fmt,...)
156 {
157         fprintf(stderr, "ERROR: %s\n", fmt);
158         proc_exit(1);
159 }
160
161 int
162 errcode(int sqlerrcode)
163 {
164         return 0;                                       /* return value does not matter */
165 }
166
167 int
168 errmsg(const char *fmt,...)
169 {
170         fprintf(stderr, "ERROR: %s\n", fmt);
171         return 0;                                       /* return value does not matter */
172 }
173
174 int
175 errmsg_internal(const char *fmt,...)
176 {
177         fprintf(stderr, "ERROR: %s\n", fmt);
178         return 0;                                       /* return value does not matter */
179 }
180
181 int
182 errdetail(const char *fmt,...)
183 {
184         fprintf(stderr, "DETAIL: %s\n", fmt);
185         return 0;                                       /* return value does not matter */
186 }
187
188 int
189 errdetail_log(const char *fmt,...)
190 {
191         fprintf(stderr, "DETAIL: %s\n", fmt);
192         return 0;                                       /* return value does not matter */
193 }
194
195 int
196 errhint(const char *fmt,...)
197 {
198         fprintf(stderr, "HINT: %s\n", fmt);
199         return 0;                                       /* return value does not matter */
200 }
201
202
203 /********* here's the actual test *********/
204
205
206 typedef struct MyStorage
207 {
208         PGShmemHeader header;
209         int                     flag;
210         PGSemaphoreData sem;
211 }       MyStorage;
212
213
214 int
215 main(int argc, char **argv)
216 {
217         MyStorage  *storage;
218         int                     cpid;
219
220         printf("Creating shared memory ... ");
221         fflush(stdout);
222
223         storage = (MyStorage *) PGSharedMemoryCreate(8192, false, 5433);
224
225         storage->flag = 1234;
226
227         printf("OK\n");
228
229         printf("Creating semaphores ... ");
230         fflush(stdout);
231
232         PGReserveSemaphores(2, 5433);
233
234         PGSemaphoreCreate(&storage->sem);
235
236         printf("OK\n");
237
238         /* sema initial value is 1, so lock should work */
239
240         printf("Testing Lock ... ");
241         fflush(stdout);
242
243         PGSemaphoreLock(&storage->sem, false);
244
245         printf("OK\n");
246
247         /* now sema value is 0, so trylock should fail */
248
249         printf("Testing TryLock ... ");
250         fflush(stdout);
251
252         if (PGSemaphoreTryLock(&storage->sem))
253                 printf("unexpected result!\n");
254         else
255                 printf("OK\n");
256
257         /* unlocking twice and then locking twice should work... */
258
259         printf("Testing Multiple Lock ... ");
260         fflush(stdout);
261
262         PGSemaphoreUnlock(&storage->sem);
263         PGSemaphoreUnlock(&storage->sem);
264
265         PGSemaphoreLock(&storage->sem, false);
266         PGSemaphoreLock(&storage->sem, false);
267
268         printf("OK\n");
269
270         /* check Reset too */
271
272         printf("Testing Reset ... ");
273         fflush(stdout);
274
275         PGSemaphoreUnlock(&storage->sem);
276
277         PGSemaphoreReset(&storage->sem);
278
279         if (PGSemaphoreTryLock(&storage->sem))
280                 printf("unexpected result!\n");
281         else
282                 printf("OK\n");
283
284         /* Fork a child process and see if it can communicate */
285
286         printf("Forking child process ... ");
287         fflush(stdout);
288
289         cpid = fork();
290         if (cpid == 0)
291         {
292                 /* In child */
293                 on_exit_reset();
294                 sleep(3);
295                 storage->flag++;
296                 PGSemaphoreUnlock(&storage->sem);
297                 proc_exit(0);
298         }
299         if (cpid < 0)
300         {
301                 /* Fork failed */
302                 printf("failed: %s\n", strerror(errno));
303                 proc_exit(1);
304         }
305
306         printf("forked child pid %d OK\n", cpid);
307
308         if (storage->flag != 1234)
309                 printf("Wrong value found in shared memory!\n");
310
311         printf("Waiting for child (should wait 3 sec here) ... ");
312         fflush(stdout);
313
314         PGSemaphoreLock(&storage->sem, false);
315
316         printf("OK\n");
317
318         if (storage->flag != 1235)
319                 printf("Wrong value found in shared memory!\n");
320
321         /* Test shutdown */
322
323         printf("Running shmem_exit processing ... ");
324         fflush(stdout);
325
326         shmem_exit(0);
327
328         printf("OK\n");
329
330         printf("Tests complete.\n");
331
332         proc_exit(0);
333
334         return 0;                                       /* not reached */
335 }