ipc_test.c 6.35 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/*-------------------------------------------------------------------------
 *
 * 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.
 *
 *
19
 * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
20 21 22 23
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
24
 *	  $PostgreSQL: pgsql/src/backend/port/ipc_test.c,v 1.19 2006/01/08 21:24:36 tgl Exp $
25 26 27 28 29
 *
 *-------------------------------------------------------------------------
 */
#include "postgres.h"

Tom Lane's avatar
Tom Lane committed
30
#include <errno.h>
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
#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;
50
bool		assert_enabled = true;
51

52 53
int			MaxBackends = 32;
int			NBuffers = 64;
54

55 56
char	   *DataDir = ".";

57 58 59 60 61

#define MAX_ON_EXITS 20

static struct ONEXIT
{
62
	void		(*function) (int code, Datum arg);
63 64 65 66 67 68 69 70 71 72 73 74
	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,
75
								  on_proc_exit_list[on_proc_exit_index].arg);
76 77 78 79 80 81 82 83
	exit(code);
}

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

void
Bruce Momjian's avatar
Bruce Momjian committed
89
			on_shmem_exit(void (*function) (int code, Datum arg), Datum arg)
90 91
{
	if (on_shmem_exit_index >= MAX_ON_EXITS)
92
		elog(FATAL, "out of on_shmem_exit slots");
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118

	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(char *conditionName,
119
					 char *errorType,
120 121 122
					 char *fileName,
					 int lineNumber)
{
123 124
	fprintf(stderr, "TRAP: %s(\"%s\", File: \"%s\", Line: %d)\n",
			errorType, conditionName,
125 126 127 128 129
			fileName, lineNumber);
	abort();
	return 0;
}

130

131 132 133 134 135
int
errcode_for_file_access(void)
{
	return 0;
}
136 137 138 139 140 141 142 143

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

144
void
Bruce Momjian's avatar
Bruce Momjian committed
145
errfinish(int dummy,...)
146 147 148 149
{
	proc_exit(1);
}

150 151 152 153 154
void
elog_start(const char *filename, int lineno, const char *funcname)
{
}

155
void
Bruce Momjian's avatar
Bruce Momjian committed
156
elog_finish(int elevel, const char *fmt,...)
157 158 159 160 161 162 163 164 165 166 167 168
{
	fprintf(stderr, "ERROR: %s\n", fmt);
	proc_exit(1);
}

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

int
Bruce Momjian's avatar
Bruce Momjian committed
169
errmsg(const char *fmt,...)
170 171 172 173 174 175
{
	fprintf(stderr, "ERROR: %s\n", fmt);
	return 0;					/* return value does not matter */
}

int
Bruce Momjian's avatar
Bruce Momjian committed
176
errmsg_internal(const char *fmt,...)
177 178 179 180 181 182
{
	fprintf(stderr, "ERROR: %s\n", fmt);
	return 0;					/* return value does not matter */
}

int
Bruce Momjian's avatar
Bruce Momjian committed
183
errdetail(const char *fmt,...)
184 185 186 187 188 189
{
	fprintf(stderr, "DETAIL: %s\n", fmt);
	return 0;					/* return value does not matter */
}

int
Bruce Momjian's avatar
Bruce Momjian committed
190
errhint(const char *fmt,...)
191
{
192 193
	fprintf(stderr, "HINT: %s\n", fmt);
	return 0;					/* return value does not matter */
194 195 196 197 198 199 200 201
}


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


typedef struct MyStorage
{
Bruce Momjian's avatar
Bruce Momjian committed
202 203 204 205
	PGShmemHeader header;
	int			flag;
	PGSemaphoreData sem;
}	MyStorage;
206 207 208 209 210


int
main(int argc, char **argv)
{
Bruce Momjian's avatar
Bruce Momjian committed
211 212
	MyStorage  *storage;
	int			cpid;
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329

	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 */
}