diff -crP postgresql-7.2b2/configure postgresql-7.2b2.patched/configure *** postgresql-7.2b2/configure Tue Nov 6 14:12:07 2001 --- postgresql-7.2b2.patched/configure Thu Nov 15 01:30:09 2001 *************** *** 686,691 **** --- 686,693 ---- # --with-template not given + echo $host_os + case $host_os in aix*) template=aix ;; beos*) template=beos ;; *************** *** 702,707 **** --- 704,710 ---- openbsd*) template=openbsd ;; osf*) template=osf ;; qnx*) template=qnx4 ;; + nto*) template=qnx6 ;; sco*) template=sco ;; solaris*) template=solaris ;; sunos*) template=sunos4 ;; diff -crP postgresql-7.2b2/configure.in postgresql-7.2b2.patched/configure.in *** postgresql-7.2b2/configure.in Tue Nov 6 14:12:07 2001 --- postgresql-7.2b2.patched/configure.in Thu Nov 8 14:00:33 2001 *************** *** 72,77 **** --- 72,78 ---- openbsd*) template=openbsd ;; osf*) template=osf ;; qnx*) template=qnx4 ;; + nto*) template=qnx6 ;; sco*) template=sco ;; solaris*) template=solaris ;; sunos*) template=sunos4 ;; diff -crP postgresql-7.2b2/src/Makefile.shlib postgresql-7.2b2.patched/src/Makefile.shlib *** postgresql-7.2b2/src/Makefile.shlib Fri Oct 5 16:15:38 2001 --- postgresql-7.2b2.patched/src/Makefile.shlib Thu Nov 8 18:49:24 2001 *************** *** 263,268 **** --- 263,274 ---- SHLIB_LINK += -ltermcap -lstdc++.r4 -lbind -lsocket -L/boot/develop/lib/x86 endif + ifeq ($(PORTNAME), qnx6) + shlib := lib$(NAME)$(DLSUFFIX).$(SO_MAJOR_VERSION).$(SO_MINOR_VERSION) + LINK.shared = $(COMPILER) -shared -Wl,-soname,$(soname) + SHLIB_LINK += -lm -lsocket -lc + endif + SHLIB_LINK := $(filter -L%, $(LDFLAGS)) $(SHLIB_LINK) ifeq ($(enable_rpath), yes) SHLIB_LINK += $(rpath) diff -crP postgresql-7.2b2/src/backend/port/Makefile.in postgresql-7.2b2.patched/src/backend/port/Makefile.in *** postgresql-7.2b2/src/backend/port/Makefile.in Tue May 8 14:38:57 2001 --- postgresql-7.2b2.patched/src/backend/port/Makefile.in Mon Nov 19 21:30:10 2001 *************** *** 30,35 **** --- 30,42 ---- ifeq ($(PORTNAME), qnx4) OBJS += getrusage.o qnx4/SUBSYS.o endif + # + # Uncomment below lines if you want to use SysV emulation on QNX6 + # But you don't want it probably. + # + #ifeq ($(PORTNAME), qnx6) + #OBJS += qnx6/SUBSYS.o + #endif ifeq ($(PORTNAME), beos) OBJS += beos/SUBSYS.o endif *************** *** 46,51 **** --- 53,67 ---- qnx4.dir: $(MAKE) -C qnx4 all + + # + # Uncomment below lines if you want to use SysV emulation on QNX6 + # See README in qnx6 directory + # + #qnx6/SUBSYS.o: qnx6.dir + + #qnx6.dir: + # $(MAKE) -C qnx6 all beos/SUBSYS.o: beos.dir diff -crP postgresql-7.2b2/src/backend/port/dynloader/qnx6.c postgresql-7.2b2.patched/src/backend/port/dynloader/qnx6.c *** postgresql-7.2b2/src/backend/port/dynloader/qnx6.c Wed Dec 31 18:00:00 1969 --- postgresql-7.2b2.patched/src/backend/port/dynloader/qnx6.c Sun Nov 4 06:54:05 2001 *************** *** 0 **** --- 1,4 ---- + /* Dummy file used for nothing at this point + * + * see qnx6.h + */ diff -crP postgresql-7.2b2/src/backend/port/dynloader/qnx6.h postgresql-7.2b2.patched/src/backend/port/dynloader/qnx6.h *** postgresql-7.2b2/src/backend/port/dynloader/qnx6.h Wed Dec 31 18:00:00 1969 --- postgresql-7.2b2.patched/src/backend/port/dynloader/qnx6.h Sun Nov 4 06:54:41 2001 *************** *** 0 **** --- 1,14 ---- + /* $Header: /home/projects/pgsql/cvsroot/pgsql/src/backend/port/dynloader/solaris.h,v 1.3 2001/03/22 03:59:43 momjian Exp $ */ + + #ifndef DYNLOADER_NEUTRINO_H + #define DYNLOADER_NEUTRINO_H + + #include + #include "utils/dynamic_loader.h" + + #define pg_dlopen(f) dlopen(f,RTLD_NOW) + #define pg_dlsym dlsym + #define pg_dlclose dlclose + #define pg_dlerror dlerror + + #endif /* DYNLOADER_NEUTRINO_H */ diff -crP postgresql-7.2b2/src/backend/port/qnx6/Makefile postgresql-7.2b2.patched/src/backend/port/qnx6/Makefile *** postgresql-7.2b2/src/backend/port/qnx6/Makefile Wed Dec 31 18:00:00 1969 --- postgresql-7.2b2.patched/src/backend/port/qnx6/Makefile Thu Nov 8 16:47:53 2001 *************** *** 0 **** --- 1,38 ---- + #------------------------------------------------------------------------- + # + # Makefile-- + # Makefile for port/sparc + # + # IDENTIFICATION + # $Header: /home/projects/pgsql/cvsroot/pgsql/src/backend/port/qnx4/Makefile,v 1.3 2000/08/31 16:10:19 petere Exp $ + # + #------------------------------------------------------------------------- + + subdir = src/backend/port/qnx6 + top_builddir = ../../../.. + include $(top_builddir)/src/Makefile.global + + CC = gcc -g + OBJS = sem.o shm.o + + all: SUBSYS.o tstsem tstshm + #all: SUBSYS.o + + SUBSYS.o: $(OBJS) + $(LD) $(LDREL) $(LDOUT) SUBSYS.o $(OBJS) + + tstsem: tstsem.o sem.o + $(CC) -o tstsem sem.o tstsem.o + + tstshm: tstshm.o shm.o + $(CC) -o tstshm shm.o tstshm.o + + depend dep: + $(CC) -MM $(CFLAGS) *.c >depend + + clean: + rm -f SUBSYS.o $(OBJS) tstrint tstsem tstsem.o tstshm tstshm.o + + ifeq (depend,$(wildcard depend)) + include depend + endif diff -crP postgresql-7.2b2/src/backend/port/qnx6/README postgresql-7.2b2.patched/src/backend/port/qnx6/README *** postgresql-7.2b2/src/backend/port/qnx6/README Wed Dec 31 18:00:00 1969 --- postgresql-7.2b2.patched/src/backend/port/qnx6/README Mon Nov 19 21:14:42 2001 *************** *** 0 **** --- 1,13 ---- + This is SysV IPC emulation (shared memory & semaphores) + for QNX6. It was inherited from QNX4 directory, but modified + to use anomymous shared memory. + + QNX6 in fact should use HAVE_POSIX_IPC code, so this is only + left here for historical/reference purposes. If for some + reason you want to use this code, uncomment lines containing + 'qnx6' in ../Makefile (and ../Makefile.in, if you want to re-run + configure). Otherwise this code is compiled, but not linked + with Postgres. + + - Igor Kovalenko + 11/19/2001 diff -crP postgresql-7.2b2/src/backend/port/qnx6/ipc.h postgresql-7.2b2.patched/src/backend/port/qnx6/ipc.h *** postgresql-7.2b2/src/backend/port/qnx6/ipc.h Wed Dec 31 18:00:00 1969 --- postgresql-7.2b2.patched/src/backend/port/qnx6/ipc.h Mon Nov 5 11:46:27 2001 *************** *** 0 **** --- 1,31 ---- + /*------------------------------------------------------------------------- + * + * ipc.h + * System V IPC Emulation + * + * Copyright (c) 1999, repas AEG Automation GmbH + * + * + * IDENTIFICATION + * $Header: /cvsroot/pgsql/src/backend/port/qnx4/ipc.h,v 1.6 2001/11/05 17:46:27 momjian Exp $ + * + *------------------------------------------------------------------------- + */ + + #ifndef _SYS_IPC_H + #define _SYS_IPC_H + + /* Common IPC definitions. */ + /* Mode bits. */ + #define IPC_CREAT 0001000 /* create entry if key doesn't exist */ + #define IPC_EXCL 0002000 /* fail if key exists */ + #define IPC_NOWAIT 0004000 /* error if request must wait */ + + /* Keys. */ + #define IPC_PRIVATE (key_t)0 /* private key */ + + /* Control Commands. */ + #define IPC_RMID 0 /* remove identifier */ + #define IPC_STAT 1 /* get shm status */ + + #endif /* _SYS_IPC_H */ diff -crP postgresql-7.2b2/src/backend/port/qnx6/sem.c postgresql-7.2b2.patched/src/backend/port/qnx6/sem.c *** postgresql-7.2b2/src/backend/port/qnx6/sem.c Wed Dec 31 18:00:00 1969 --- postgresql-7.2b2.patched/src/backend/port/qnx6/sem.c Mon Nov 19 19:15:22 2001 *************** *** 0 **** --- 1,348 ---- + /*------------------------------------------------------------------------- + * + * sem.c + * System V Semaphore Emulation + * + * Copyright (c) 1999, repas AEG Automation GmbH + * Copyright (c) 2001, Igor Kovalenko ikovalenko@sourceforge.net + * + * - Original code was changed to use anonymous shared memory + * + * IDENTIFICATION + * $Header: /cvsroot/pgsql/src/backend/port/qnx4/sem.c,v 1.9 2001/10/28 06:25:47 momjian Exp $ + * + *------------------------------------------------------------------------- + */ + + #include "postgres.h" + + #include + #include + #include + #include + #include + #include + #include + #include + #include + + #include "miscadmin.h" + #include "storage/ipc.h" + #include "storage/proc.h" + + + #define SEMMAX (PROC_NSEMS_PER_SET+1) + #define OPMAX 8 + + struct pending_ops + { + int op[OPMAX]; /* array of pending operations */ + int idx; /* index of first free array member */ + }; + + struct sem_set_info + { + key_t key; + int nsems; + sem_t sem[SEMMAX]; /* array of POSIX semaphores */ + struct sem semV[SEMMAX]; /* array of System V semaphore structures */ + struct pending_ops pendingOps[SEMMAX]; /* array of pending + * operations */ + }; + + struct sem_info + { + sem_t sem; + int nsets; + /* there are actually nsets of these: */ + struct sem_set_info set[1]; /* VARIABLE LENGTH ARRAY */ + }; + + static struct sem_info *SemInfo = (struct sem_info *) - 1; + + int + semctl(int semid, int semnum, int cmd, ... ) + { + int r = 0; + va_list arg_list; + union semun arg; + + va_start(arg_list, cmd); + arg = va_arg(arg_list, union semun); + va_end(arg_list); + + sem_wait(&SemInfo->sem); + + if (semid < 0 || semid >= SemInfo->nsets || + semnum < 0 || semnum >= SemInfo->set[semid].nsems) + { + sem_post(&SemInfo->sem); + errno = EINVAL; + return -1; + } + + switch (cmd) + { + case GETNCNT: + r = SemInfo->set[semid].semV[semnum].semncnt; + break; + + case GETPID: + r = SemInfo->set[semid].semV[semnum].sempid; + break; + + case GETVAL: + r = SemInfo->set[semid].semV[semnum].semval; + break; + + case GETALL: + for (semnum = 0; semnum < SemInfo->set[semid].nsems; semnum++) + arg.array[semnum] = SemInfo->set[semid].semV[semnum].semval; + break; + + case SETVAL: + SemInfo->set[semid].semV[semnum].semval = arg.val; + break; + + case SETALL: + for (semnum = 0; semnum < SemInfo->set[semid].nsems; semnum++) + SemInfo->set[semid].semV[semnum].semval = arg.array[semnum]; + break; + + case GETZCNT: + r = SemInfo->set[semid].semV[semnum].semzcnt; + break; + + case IPC_RMID: + for (semnum = 0; semnum < SemInfo->set[semid].nsems; semnum++) + { + if (sem_destroy(&SemInfo->set[semid].sem[semnum]) == -1) + r = -1; + } + SemInfo->set[semid].key = -1; + SemInfo->set[semid].nsems = 0; + break; + + default: + sem_post(&SemInfo->sem); + errno = EINVAL; + return -1; + } + + sem_post(&SemInfo->sem); + + return r; + } + + int + semget(key_t key, int nsems, int semflg) + { + int semid, + semnum, + nsets; + Size sem_info_size; + struct stat statbuf; + + if (nsems < 0 || nsems > SEMMAX) + { + errno = EINVAL; + return -1; + } + + /* open and map shared memory */ + if (SemInfo == (struct sem_info *) - 1) + { + SemInfo = mmap(NULL, sem_info_size, + PROT_READ | PROT_WRITE, MAP_ANON|MAP_SHARED, -1, 0); + if (SemInfo == MAP_FAILED) + return -1; + /* initialize shared memory */ + memset(SemInfo, 0, sem_info_size); + SemInfo->nsets = nsets; + for (semid = 0; semid < nsets; semid++) + SemInfo->set[semid].key = -1; + /* create semaphore for locking */ + sem_init(&SemInfo->sem, 1, 1); + } + + sem_wait(&SemInfo->sem); + nsets = SemInfo->nsets; + + if (key != IPC_PRIVATE) + { + /* search existing element */ + semid = 0; + while (semid < nsets && SemInfo->set[semid].key != key) + semid++; + if (!(semflg & IPC_CREAT) && semid >= nsets) + { + sem_post(&SemInfo->sem); + errno = ENOENT; + return -1; + } + else if (semid < nsets) + { + if (semflg & IPC_CREAT && semflg & IPC_EXCL) + { + sem_post(&SemInfo->sem); + errno = EEXIST; + return -1; + } + else + { + if (nsems != 0 && SemInfo->set[semid].nsems < nsems) + { + sem_post(&SemInfo->sem); + errno = EINVAL; + return -1; + } + sem_post(&SemInfo->sem); + return semid; + } + } + } + + /* search first free element */ + semid = 0; + while (semid < nsets && SemInfo->set[semid].key != -1) + semid++; + if (semid >= nsets) + { + sem_post(&SemInfo->sem); + errno = ENOSPC; + return -1; + } + + for (semnum = 0; semnum < nsems; semnum++) + { + sem_init(&SemInfo->set[semid].sem[semnum], 1, 0); + /* Currently sem_init always returns -1. */ + #ifdef NOT_USED + if (sem_init(&SemInfo->set[semid].sem[semnum], 1, 0) == -1) + { + int semnum1; + + for (semnum1 = 0; semnum1 < semnum; semnum1++) + sem_destroy(&SemInfo->set[semid].sem[semnum1]); + sem_post(&SemInfo->sem); + return -1; + } + #endif + } + + SemInfo->set[semid].key = key; + SemInfo->set[semid].nsems = nsems; + + sem_post(&SemInfo->sem); + + return semid; + } + + int + semop(int semid, struct sembuf * sops, size_t nsops) + { + int i, + r = 0, + r1, + errno1 = 0, + op; + + sem_wait(&SemInfo->sem); + + if (semid < 0 || semid >= SemInfo->nsets) + { + sem_post(&SemInfo->sem); + errno = EINVAL; + return -1; + } + for (i = 0; i < nsops; i++) + { + if ( /* sops[i].sem_num < 0 || */ sops[i].sem_num >= SemInfo->set[semid].nsems) + { + sem_post(&SemInfo->sem); + errno = EFBIG; + return -1; + } + } + + for (i = 0; i < nsops; i++) + { + if (sops[i].sem_op < 0) + { + if (SemInfo->set[semid].semV[sops[i].sem_num].semval < -sops[i].sem_op) + { + if (sops[i].sem_flg & IPC_NOWAIT) + { + sem_post(&SemInfo->sem); + errno = EAGAIN; + return -1; + } + SemInfo->set[semid].semV[sops[i].sem_num].semncnt++; + if (SemInfo->set[semid].pendingOps[sops[i].sem_num].idx >= OPMAX) + { + /* pending operations array overflow */ + sem_post(&SemInfo->sem); + errno = ERANGE; + return -1; + } + SemInfo->set[semid].pendingOps[sops[i].sem_num].op[SemInfo->set[semid].pendingOps[sops[i].sem_num].idx++] = sops[i].sem_op; + /* suspend */ + sem_post(&SemInfo->sem); /* avoid deadlock */ + r1 = sem_wait(&SemInfo->set[semid].sem[sops[i].sem_num]); + sem_wait(&SemInfo->sem); + if (r1) + { + errno1 = errno; + r = r1; + /* remove pending operation */ + SemInfo->set[semid].pendingOps[sops[i].sem_num].op[--SemInfo->set[semid].pendingOps[sops[i].sem_num].idx] = 0; + } + else + SemInfo->set[semid].semV[sops[i].sem_num].semval -= -sops[i].sem_op; + SemInfo->set[semid].semV[sops[i].sem_num].semncnt--; + } + else + SemInfo->set[semid].semV[sops[i].sem_num].semval -= -sops[i].sem_op; + } + else if (sops[i].sem_op > 0) + { + SemInfo->set[semid].semV[sops[i].sem_num].semval += sops[i].sem_op; + op = sops[i].sem_op; + while (op > 0 && SemInfo->set[semid].pendingOps[sops[i].sem_num].idx > 0) + { /* operations pending */ + if (SemInfo->set[semid].pendingOps[sops[i].sem_num].op[SemInfo->set[semid].pendingOps[sops[i].sem_num].idx - 1] + op >= 0) + { + /* unsuspend processes */ + if (sem_post(&SemInfo->set[semid].sem[sops[i].sem_num])) + { + errno1 = errno; + r = -1; + } + /* adjust pending operations */ + op += SemInfo->set[semid].pendingOps[sops[i].sem_num].op[--SemInfo->set[semid].pendingOps[sops[i].sem_num].idx]; + SemInfo->set[semid].pendingOps[sops[i].sem_num].op[SemInfo->set[semid].pendingOps[sops[i].sem_num].idx] = 0; + } + else + { + /* adjust pending operations */ + SemInfo->set[semid].pendingOps[sops[i].sem_num].op[SemInfo->set[semid].pendingOps[sops[i].sem_num].idx - 1] += op; + op = 0; + } + } + } + else + /* sops[i].sem_op == 0 */ + { + /* not supported */ + sem_post(&SemInfo->sem); + errno = ENOSYS; + return -1; + } + SemInfo->set[semid].semV[sops[i].sem_num].sempid = getpid(); + } + + sem_post(&SemInfo->sem); + + errno = errno1; + return r; + } diff -crP postgresql-7.2b2/src/backend/port/qnx6/sem.h postgresql-7.2b2.patched/src/backend/port/qnx6/sem.h *** postgresql-7.2b2/src/backend/port/qnx6/sem.h Wed Dec 31 18:00:00 1969 --- postgresql-7.2b2.patched/src/backend/port/qnx6/sem.h Thu Nov 8 14:18:32 2001 *************** *** 0 **** --- 1,68 ---- + /*------------------------------------------------------------------------- + * + * sem.h + * System V Semaphore Emulation + * + * Copyright (c) 1999, repas AEG Automation GmbH + * + * + * IDENTIFICATION + * $Header: /cvsroot/pgsql/src/backend/port/qnx4/sem.h,v 1.6 2001/11/05 17:46:27 momjian Exp $ + * + *------------------------------------------------------------------------- + */ + + #ifndef _SYS_SEM_H + #define _SYS_SEM_H + + #include "ipc.h" + + #ifdef __cplusplus + extern "C" + { + #endif + + /* + * Semctl Command Definitions. + */ + + #define GETNCNT 3 /* get semncnt */ + #define GETPID 4 /* get sempid */ + #define GETVAL 5 /* get semval */ + #define GETALL 6 /* get all semval's */ + #define GETZCNT 7 /* get semzcnt */ + #define SETVAL 8 /* set semval */ + #define SETALL 9 /* set all semval's */ + + /* + * There is one semaphore structure for each semaphore in the system. + */ + + struct sem + { + ushort_t semval; /* semaphore text map address */ + pid_t sempid; /* pid of last operation */ + ushort_t semncnt; /* # awaiting semval > cval */ + ushort_t semzcnt; /* # awaiting semval = 0 */ + }; + + /* + * User semaphore template for semop system calls. + */ + + struct sembuf + { + ushort_t sem_num; /* semaphore # */ + short sem_op; /* semaphore operation */ + short sem_flg; /* operation flags */ + }; + + extern int semctl(int semid, int semnum, int cmd, /* ... */ union semun arg); + extern int semget(key_t key, int nsems, int semflg); + extern int semop(int semid, struct sembuf * sops, size_t nsops); + + #ifdef __cplusplus + } + #endif + + #endif /* _SYS_SEM_H */ diff -crP postgresql-7.2b2/src/backend/port/qnx6/shm.c postgresql-7.2b2.patched/src/backend/port/qnx6/shm.c *** postgresql-7.2b2/src/backend/port/qnx6/shm.c Wed Dec 31 18:00:00 1969 --- postgresql-7.2b2.patched/src/backend/port/qnx6/shm.c Thu Nov 8 14:42:31 2001 *************** *** 0 **** --- 1,276 ---- + /*------------------------------------------------------------------------- + * + * shm.c + * System V Shared Memory Emulation + * + * Copyright (c) 1999, repas AEG Automation GmbH + * + * + * IDENTIFICATION + * $Header: /cvsroot/pgsql/src/backend/port/qnx4/shm.c,v 1.7 2001/10/25 05:49:40 momjian Exp $ + * + *------------------------------------------------------------------------- + */ + + #include "postgres.h" + + #include + #include + #include + #include + #include + #include + #include "shm.h" + #include + + + #define MODE 0777 + + #define SHMMAX 1024 + + + struct shm_info + { + int shmid; + key_t key; + size_t size; + void *addr; + }; + + static struct shm_info *ShmInfo; + + + static int shm_putinfo(struct shm_info * info); + static int shm_updinfo(int i, struct shm_info * info); + static int shm_getinfo(int shmid, struct shm_info * info); + static int shm_getinfobyaddr(const void *addr, struct shm_info * info); + + static char * + keytoname(key_t key, char *name) + { + sprintf(name, "PgShm%x", key); + return name; + } + + static int + shm_putinfo(struct shm_info * info) + { + int i; + + if (ShmInfo == NULL) + { + ShmInfo = calloc(SHMMAX, sizeof(struct shm_info)); + if (ShmInfo == NULL) + return -1; + /* initialize ShmInfo */ + for (i = 0; i < SHMMAX; i++) + ShmInfo[i].shmid = -1; + } + + /* search first free element */ + i = 0; + while (i < SHMMAX && ShmInfo[i].shmid != -1) + i++; + if (i >= SHMMAX) + { + errno = ENOSPC; + return -1; + } + + memcpy(&ShmInfo[i], info, sizeof(struct shm_info)); + + return i; + } + + static int + shm_updinfo(int i, struct shm_info * info) + { + if (i >= SHMMAX) + return -1; + if (ShmInfo == NULL) + return -1; + + memcpy(&ShmInfo[i], info, sizeof(struct shm_info)); + + return i; + } + + static int + shm_getinfo(int shmid, struct shm_info * info) + { + int i; + + if (ShmInfo == NULL) + return -1; + + /* search element */ + i = 0; + while (i < SHMMAX && ShmInfo[i].shmid != shmid) + i++; + if (i >= SHMMAX) + return -1; + + memcpy(info, &ShmInfo[i], sizeof(struct shm_info)); + + return i; + } + + static int + shm_getinfobyaddr(const void *addr, struct shm_info * info) + { + int i; + + if (ShmInfo == (struct shm_info *) - 1) + return -1; + + /* search element */ + i = 0; + while (i < SHMMAX && ShmInfo[i].addr != addr) + i++; + if (i >= SHMMAX) + return -1; + + memcpy(info, &ShmInfo[i], sizeof(struct shm_info)); + + return i; + } + + + void * + shmat(int shmid, const void *shmaddr, int shmflg) + { + struct shm_info info; + int i; + + i = shm_getinfo(shmid, &info); + if (i == -1) + { + errno = EACCES; + return (void *) -1; + } + + info.addr = mmap((void *) shmaddr, info.size, + PROT_READ | PROT_WRITE, MAP_SHARED, shmid, 0); + if (info.addr == MAP_FAILED) + return info.addr; + + if (shm_updinfo(i, &info) == -1) + { + errno = EACCES; + return (void *) -1; + } + + return info.addr; + } + + int + shmdt(const void *addr) + { + struct shm_info info; + + if (shm_getinfobyaddr(addr, &info) == -1) + { + errno = EACCES; + return -1; + } + + return munmap((void *) addr, info.size); + } + + int + shmctl(int shmid, int cmd, struct shmid_ds * buf) + { + struct shm_info info; + char name[NAME_MAX + 1]; + int result; + int fd; + struct stat statbuf; + + + switch (cmd) + { + case IPC_RMID: + if (shm_getinfo(shmid, &info) == -1) + { + errno = EACCES; + return -1; + } + close(info.shmid); + keytoname(info.key, name); + return shm_unlink(name); + + case IPC_STAT: + + /* + * we have to open it first. stat() does no prefix tracking -> + * the call would go to fsys instead of proc + */ + keytoname(shmid, name); + fd = shm_open(name, 0, MODE); + if (fd >= 0) + { + result = fstat(fd, &statbuf); + + /* + * if the file exists, subtract 2 from linkcount : one for + * our own open and one for the dir entry + */ + if (!result) + buf->shm_nattch = statbuf.st_nlink - 2; + close(fd); + return result; + } + else + { + /* + * if there's no entry for this key it doesn't matter the + * next shmget() would get a different shm anyway + */ + buf->shm_nattch = 0; + return 0; + } + } + errno = EINVAL; + return -1; + } + + int + shmget(key_t key, size_t size, int flags) + { + char name[NAME_MAX + 1]; + int oflag = 0; + struct shm_info info; + + if (flags & IPC_CREAT) + oflag |= O_CREAT; + if (flags & IPC_EXCL) + oflag |= O_EXCL; + if (flags & SHM_R) + { + if (flags & SHM_W) + oflag |= O_RDWR; + else + oflag |= O_RDONLY; + } + info.shmid = shm_open(keytoname(key, name), oflag, MODE); + + /* store shared memory information */ + if (info.shmid != -1) + { + info.key = key; + info.size = size; + info.addr = NULL; + if (shm_putinfo(&info) == -1) + { + close(info.shmid); + if ((oflag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) + shm_unlink(name); + return -1; + } + } + + /* The size may only be set once. Ignore errors. */ + ftruncate(info.shmid, size); + + return info.shmid; + } diff -crP postgresql-7.2b2/src/backend/port/qnx6/shm.h postgresql-7.2b2.patched/src/backend/port/qnx6/shm.h *** postgresql-7.2b2/src/backend/port/qnx6/shm.h Wed Dec 31 18:00:00 1969 --- postgresql-7.2b2.patched/src/backend/port/qnx6/shm.h Mon Nov 5 11:46:27 2001 *************** *** 0 **** --- 1,43 ---- + /*------------------------------------------------------------------------- + * + * shm.h + * System V Shared Memory Emulation + * + * Copyright (c) 1999, repas AEG Automation GmbH + * + * + * IDENTIFICATION + * $Header: /cvsroot/pgsql/src/backend/port/qnx4/shm.h,v 1.6 2001/11/05 17:46:27 momjian Exp $ + * + *------------------------------------------------------------------------- + */ + + #ifndef _SYS_SHM_H + #define _SYS_SHM_H + + #include + + #ifdef __cplusplus + extern "C" + { + #endif + + #define SHM_R 0400 /* read permission */ + #define SHM_W 0200 /* write permission */ + + struct shmid_ds + { + int dummy; + int shm_nattch; + }; + + extern void *shmat(int shmid, const void *shmaddr, int shmflg); + extern int shmdt(const void *addr); + extern int shmctl(int shmid, int cmd, struct shmid_ds * buf); + extern int shmget(key_t key, size_t size, int flags); + + #ifdef __cplusplus + } + #endif + + #endif /* _SYS_SHM_H */ diff -crP postgresql-7.2b2/src/backend/port/qnx6/tstsem.c postgresql-7.2b2.patched/src/backend/port/qnx6/tstsem.c *** postgresql-7.2b2/src/backend/port/qnx6/tstsem.c Wed Dec 31 18:00:00 1969 --- postgresql-7.2b2.patched/src/backend/port/qnx6/tstsem.c Thu Nov 8 16:15:01 2001 *************** *** 0 **** --- 1,208 ---- + /*------------------------------------------------------------------------- + * + * tstsem.c + * Test of System V Semaphore Emulation + * + * Copyright (c) 1999, repas AEG Automation GmbH + * + * + * IDENTIFICATION + * $Header: /cvsroot/pgsql/src/backend/port/qnx4/tstsem.c,v 1.6 2001/10/25 05:49:40 momjian Exp $ + * + *------------------------------------------------------------------------- + */ + + #include "postgres.h" + + #include + #include + #include + #include + #include "storage/ipc.h" + #include + #include + + + #define SEMMAX 16 + #define OPSMAX 1 + + static int semid; + + int MaxBackends = 32; + + static void + sig_handler(int sig_no) + { + union semun arg; + int i = semctl(semid, 0, GETNCNT, arg); + + if (i == -1) + perror("semctl"); + else + printf("semval = %d\n", i); + } + + void on_proc_exit(void (*function) (), Datum arg) + { + atexit(function); + } + int + main(int argc, char **argv) + { + int c, + errflg = 0; + char s[80]; + key_t key = IPC_PRIVATE; + int nsems = SEMMAX; + int semflg = 0; + int unlink = 0; + int i; + struct sembuf sops[OPSMAX]; + u_short array[SEMMAX]; + union semun arg; + + optarg = NULL; + while (!errflg && (c = getopt(argc, argv, "k:n:cxu")) != -1) + { + switch (c) + { + case 'k': + key = atoi(optarg); + break; + case 'n': + nsems = atoi(optarg); + break; + case 'c': + semflg |= IPC_CREAT; + break; + case 'x': + semflg |= IPC_EXCL; + break; + case 'u': + unlink = 1; + break; + default: + errflg++; + } + } + if (errflg) + { + printf("usage: tstsem [-k key] [-n nsems] [-cxu]\n"); + exit(1); + } + + if (unlink) + { + i = shm_unlink("SysV_Sem_Info"); + if (i == -1) + perror("shm_unlink"); + exit(i); + } + + semid = semget(key, nsems, semflg); + if (semid == -1) + { + perror("semget"); + exit(semid); + } + + /* test signal interrupts */ + signal(SIGTERM, sig_handler); + + do + { + printf("(-)sem_op, (+)sem_op, (G)ETVAL, (S)ETVAL, GET(P)ID, GET(A)LL, SETA(L)L, GET(N)CNT, GET(Z)CNT, e(x)it: "); + scanf("%s", s); + switch (s[0]) + { + case '-': + case '+': + sops[0].sem_num = 0; + sops[0].sem_op = atoi(s); + if (sops[0].sem_op == 0) + sops[0].sem_op = s[0] == '+' ? +1 : -1; + sops[0].sem_flg = 0; + if (semop(semid, sops, 1) == -1) + perror("semop"); + break; + + case 'G': + case 'g': + i = semctl(semid, 0, GETVAL, arg); + if (i == -1) + perror("semctl"); + else + printf("semval = %d\n", i); + break; + + case 'S': + case 's': + printf("semval = "); + scanf("%d", &arg.val); + if (semctl(semid, 0, SETVAL, arg) == -1) + perror("semctl"); + break; + + case 'P': + case 'p': + i = semctl(semid, 0, GETPID, arg); + if (i == -1) + perror("semctl"); + else + printf("PID = %d\n", i); + break; + + case 'A': + case 'a': + arg.array = array; + i = semctl(semid, 0, GETALL, arg); + if (i == -1) + perror("semctl"); + else + { + for (i = 0; i < nsems; i++) + printf("semval[%d] = %hu\n", i, arg.array[i]); + } + break; + + case 'L': + case 'l': + arg.array = array; + for (i = 0; i < nsems; i++) + { + printf("semval[%d] = ", i); + scanf("%hu", &arg.array[i]); + } + if (semctl(semid, 0, SETALL, arg) == -1) + perror("semctl"); + break; + + case 'N': + case 'n': + i = semctl(semid, 0, GETNCNT, arg); + if (i == -1) + perror("semctl"); + else + printf("semval = %d\n", i); + break; + + case 'Z': + case 'z': + i = semctl(semid, 0, GETZCNT, arg); + if (i == -1) + perror("semctl"); + else + printf("semval = %d\n", i); + break; + } + } + while (s[0] != 'x'); + + if (semctl(semid, 0, IPC_RMID, arg) == -1) + { + perror("semctl"); + exit(-1); + } + + exit(0); + } diff -crP postgresql-7.2b2/src/backend/port/qnx6/tstshm.c postgresql-7.2b2.patched/src/backend/port/qnx6/tstshm.c *** postgresql-7.2b2/src/backend/port/qnx6/tstshm.c Wed Dec 31 18:00:00 1969 --- postgresql-7.2b2.patched/src/backend/port/qnx6/tstshm.c Thu Nov 8 16:19:43 2001 *************** *** 0 **** --- 1,100 ---- + /*------------------------------------------------------------------------- + * + * tstshm.c + * Test of System V Shared Memory Emulation + * + * Copyright (c) 1999, repas AEG Automation GmbH + * + * + * IDENTIFICATION + * $Header: /cvsroot/pgsql/src/backend/port/qnx4/tstshm.c,v 1.3 2001/08/24 14:07:49 petere Exp $ + * + *------------------------------------------------------------------------- + */ + + #include "postgres.h" + + #include + #include + #include + #include "shm.h" + + + int + main(int argc, char **argv) + { + int c, + errflg = 0; + char s[80]; + key_t key = 0x1000; + size_t size = 256; + int shmid = -1; + caddr_t addr = NULL; + + optarg = NULL; + while (!errflg && (c = getopt(argc, argv, "k:s:")) != -1) + { + switch (c) + { + case 'k': + key = atoi(optarg); + break; + case 's': + size = atoi(optarg); + break; + default: + errflg++; + } + } + if (errflg) + { + printf("usage: tstshm [-k key] [-s size]\n"); + exit(1); + } + + do + { + printf("shm(g)et, shm(a)t, shm(d)t, shm(c)tl, (w)rite, (r)ead, e(x)it: "); + scanf("%s", s); + switch (s[0]) + { + case 'g': + shmid = shmget(key, size, IPC_CREAT | SHM_R | SHM_W); + if (shmid == -1) + perror("shmget"); + break; + + case 'a': + addr = shmat(shmid, NULL, 0); + if (addr == (void *) -1) + perror("shmat"); + break; + + case 'd': + if (shmdt(addr) == -1) + perror("shmdt"); + else + addr = NULL; + break; + + case 'c': + if (shmctl(shmid, IPC_RMID, NULL) == -1) + perror("shmctl"); + else + shmid = -1; + break; + + case 'w': + printf("String to write: "); + scanf("%s", addr); + break; + + case 'r': + puts(addr); + break; + } + } + while (s[0] != 'x'); + + return 0; + } diff -crP postgresql-7.2b2/src/backend/storage/ipc/ipc.c postgresql-7.2b2.patched/src/backend/storage/ipc/ipc.c *** postgresql-7.2b2/src/backend/storage/ipc/ipc.c Mon Nov 5 11:46:28 2001 --- postgresql-7.2b2.patched/src/backend/storage/ipc/ipc.c Sat Nov 17 23:32:28 2001 *************** *** 33,38 **** --- 33,41 ---- #include #include "storage/ipc.h" + + #ifndef HAVE_POSIX_IPC + /* In Ultrix, sem.h and shm.h must be included AFTER ipc.h */ #ifdef HAVE_SYS_SEM_H #include *************** *** 40,58 **** #ifdef HAVE_SYS_SHM_H #include #endif ! #ifdef HAVE_KERNEL_OS_H ! #include #endif #if defined(__darwin__) #include "port/darwin/sem.h" #endif #include "miscadmin.h" #include "utils/memutils.h" #include "libpq/libpq.h" - /* * This flag is set during proc_exit() to change elog()'s behavior, * so that an elog() from an on_proc_exit routine cannot get us out --- 43,67 ---- #ifdef HAVE_SYS_SHM_H #include #endif ! ! #if defined(__QNXNTO__) ! #include "../backend/port/qnx6/shm.h" #endif #if defined(__darwin__) #include "port/darwin/sem.h" #endif + #endif /* HAVE_POSIX_IPC */ + + #ifdef HAVE_KERNEL_OS_H + #include + #endif + #include "miscadmin.h" #include "utils/memutils.h" #include "libpq/libpq.h" /* * This flag is set during proc_exit() to change elog()'s behavior, * so that an elog() from an on_proc_exit routine cannot get us out *************** *** 60,65 **** --- 69,75 ---- */ bool proc_exit_inprogress = false; + #ifndef HAVE_POSIX_IPC static IpcSemaphoreId InternalIpcSemaphoreCreate(IpcSemaphoreKey semKey, int numSems, int permission, int semStartValue, bool removeOnExit); *************** *** 70,75 **** --- 80,86 ---- static void IpcMemoryDelete(int status, Datum shmId); static void *PrivateMemoryCreate(uint32 size); static void PrivateMemoryDelete(int status, Datum memaddr); + #endif /* HAVE_POSIX_IPC */ /* ---------------------------------------------------------------- *************** *** 86,91 **** --- 97,105 ---- * * XXX these functions probably ought to live in some other module. * ---------------------------------------------------------------- + * + * XXX it is unclear to me whether or not all this mess is required + * with POSIX IPC. So far I assume it is - i.k. */ #define MAX_ON_EXITS 20 *************** *** 234,239 **** --- 248,488 ---- on_proc_exit_index = 0; } + #ifdef HAVE_POSIX_IPC + + /* + Use POSIX semaphores and anonymous shared memory via mmap(). + That means we don't need to worry about crap like finding keys, + detecting and removing leftovers, registering cleanup handlers + and whatever else SysV IPC requires one to do. + + We just ask system to allocate anunymous semaphores and put + them into anonymous shared segment. That all is cleaned up by + OS when process terminates for whatever reason. Easy, clean + and fast. + + OTOH, since POSIX semaphores are in process space, and are not + scalar objects, they need to be explicitly placed into shared + segment. Just returning 'id' to store in shared memory does not + work. So our 'create' routine expects caller to provide storage + and make arrangements about sharing it. + + That means we need little hacks in proc.c & spin.c as well. + Basically, storage for POSIX semaphores will be allocated within + global shared segment, along with SemId. It then becomes really + redundant to even have SemId there, but that way we can keep + semaphore API changes between SysV & POSIX to minimum. + */ + void IpcInitKeyAssignment(int port) + { + port = port; + } + + static void + CallbackSemaphoreKill(int status, Datum semId) + { + IpcSemaphoreKill((IpcSemaphoreId)DatumGetPointer(semId)); + } + + IpcSemaphoreId IpcSemaphoreCreate(void *storage, bool shared, + int semStartValue, + bool removeOnExit) + { + IpcSemaphoreId semp = (IpcSemaphoreId)storage; + + if (!semp) + { + if (shared) + { + fprintf(stderr, "IpcSemaphoreCreate(shared): No storage\n"); + proc_exit(255); + } + if ((semp = malloc(sizeof(sem_t))) < 0) + { + fprintf(stderr, "IpcSemaphoreCreate(): malloc(%d) failed: %s\n", + sizeof(sem_t), strerror(errno)); + proc_exit(255); + } + } + + if (sem_init(semp, shared, semStartValue) < 0) + { + fprintf(stderr, "IpcSemaphoreCreate: sem_init(%d) failed: %s\n", + semStartValue, strerror(errno)); + if (errno == ENOSPC) + fprintf(stderr, + "\nThis error does *not* mean that you have run out of disk space.\n" + "\n" + "It occurs when either the system limit for the maximum number of\n" + "POSIX semaphores would be exceeded. You need to raise the\n" + "respective kernel parameter. Alternatively, reduce PostgreSQL's\n" + "consumption of semaphores by reducing its max_connections parameter\n" + "(currently %d).\n" + "\n" + "The PostgreSQL Administrator's Guide contains more information about\n" + "configuring your system for PostgreSQL.\n\n", + MaxBackends); + proc_exit(255); + } + + if (removeOnExit) + on_shmem_exit(CallbackSemaphoreKill, PointerGetDatum(semp)); + + return semp; + } + + void IpcSemaphoreKill(IpcSemaphoreId semId) + { + if (sem_destroy(semId) < 0) + fprintf(stderr, "IpcSemaphoreKill: sem_destroy(%p) failed: %s\n", + semId, strerror(errno)); + /* + We don't free memory allocated for private semaphores here, + because we don't know if we should. It will be responsibility of + caller. + */ + } + + void IpcSemaphoreLock(IpcSemaphoreId semId, int sem, bool interruptOK) + { + int errStatus; + + do + { + ImmediateInterruptOK = interruptOK; + CHECK_FOR_INTERRUPTS(); + errStatus = sem_wait(semId); + ImmediateInterruptOK = false; + } while (errStatus == -1 && errno == EINTR); + + if (errStatus == -1) + { + fprintf(stderr, "IpcSemaphoreLock: sem_wait(id=%d) failed: %s\n", + sem, strerror(errno)); + proc_exit(255); + } + } + + void IpcSemaphoreUnlock(IpcSemaphoreId semId, int sem) + { + int errStatus; + + do + { + errStatus = sem_post(semId); + } while (errStatus == -1 && errno == EINTR); + + if (errStatus == -1) + { + fprintf(stderr, "IpcSemaphoreUnlock: sem_post(id=%d) failed: %s\n", + sem, strerror(errno)); + proc_exit(255); + } + } + + bool IpcSemaphoreTryLock(IpcSemaphoreId semId, int sem) + { + int errStatus; + + /* + * Note: if errStatus is -1 and errno == EINTR then it means we + * returned from the operation prematurely because we were sent a + * signal. So we try and lock the semaphore again. + */ + do + { + errStatus = sem_trywait(semId); + } while (errStatus == -1 && errno == EINTR); + + if (errStatus == -1) + { + /* Expect EAGAIN or EWOULDBLOCK (platform-dependent) */ + #ifdef EAGAIN + if (errno == EAGAIN) + return false; /* failed to lock it */ + #endif + #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN)) + if (errno == EWOULDBLOCK) + return false; /* failed to lock it */ + #endif + /* Otherwise we got trouble */ + fprintf(stderr, "IpcSemaphoreTryLock: sem_trywait(id=%d) failed: %s\n", + sem, strerror(errno)); + proc_exit(255); + } + + return true; + } + + int IpcSemaphoreGetValue(IpcSemaphoreId semId, int sem) + { + int value = -1; + + if (sem_getvalue(semId, &value) < 0) + fprintf(stderr, "IpcSemaphoreGetValue: sem_getvalue(id=%d) failed: %s\n", + sem, strerror(errno)); + return value; + } + + static void + IpcMemoryDetach(int status, Datum shmaddr) + { + void *p = DatumGetPointer(shmaddr); + + if (munmap(p, ((PGShmemHeader *)p)->totalsize) < 0) + fprintf(stderr, "IpcMemoryDetach: munmap(%p) failed: %s\n", + DatumGetPointer(shmaddr), strerror(errno)); + } + + PGShmemHeader * + IpcMemoryCreate(uint32 size, bool makePrivate, int permission) + { + void *memAddress; + PGShmemHeader *hdr; + + /* Room for a header? */ + Assert(size > MAXALIGN(sizeof(PGShmemHeader))); + + memAddress = mmap(0, size, PROT_READ|PROT_WRITE, + MAP_ANON|(makePrivate ? MAP_PRIVATE : MAP_SHARED), -1, 0); + if (memAddress == (void *) -1) + { + fprintf(stderr, "IpcMemoryCreate(size=%d): mmap() failed: %s\n", + size, strerror(errno)); + proc_exit(255); + } + hdr = (PGShmemHeader *) memAddress; + + /* + * OK, we created a new segment. Mark it as created by this process. + * The order of assignments here is critical so that another Postgres + * process can't see the header as valid but belonging to an invalid + * PID! + */ + hdr = (PGShmemHeader *) memAddress; + /* + hdr->creatorPID = getpid(); + hdr->magic = PGShmemMagic; + */ + /* + * Initialize space allocation status for segment. + */ + hdr->totalsize = size; + hdr->freeoffset = MAXALIGN(sizeof(PGShmemHeader)); + + /* Register on-exit routine to delete the new segment */ + on_shmem_exit(IpcMemoryDetach, PointerGetDatum(hdr)); + + return hdr; + } + + bool + SharedMemoryIsInUse(IpcMemoryKey shmKey, IpcMemoryId shmId) + { + return false; + } + + #else /* no POSIX IPC */ /* ---------------------------------------------------------------- * Semaphore support *************** *** 530,536 **** return semctl(semId, sem, GETPID, dummy); } - /* ---------------------------------------------------------------- * Shared memory support * --- 779,784 ---- *************** *** 980,982 **** --- 1228,1231 ---- return semId; } + #endif /* HAVE_POSIX_IPC */ diff -crP postgresql-7.2b2/src/backend/storage/lmgr/proc.c postgresql-7.2b2.patched/src/backend/storage/lmgr/proc.c *** postgresql-7.2b2/src/backend/storage/lmgr/proc.c Mon Nov 5 18:38:26 2001 --- postgresql-7.2b2.patched/src/backend/storage/lmgr/proc.c Sat Nov 17 22:16:22 2001 *************** *** 52,57 **** --- 52,60 ---- #include #include "storage/ipc.h" + + #ifndef HAVE_POSIX_IPC + /* In Ultrix, sem.h and shm.h must be included AFTER ipc.h */ #ifdef HAVE_SYS_SEM_H #include *************** *** 61,66 **** --- 64,71 ---- #include "port/darwin/sem.h" #endif + #endif /* HAVE_POSIX_IPC */ + #include "miscadmin.h" #include "access/xact.h" #include "storage/proc.h" *************** *** 152,158 **** for (i = 0; i < semMapEntries; i++) { ! ProcGlobal->procSemMap[i].procSemId = -1; ProcGlobal->procSemMap[i].freeSemMap = 0; } --- 157,163 ---- for (i = 0; i < semMapEntries; i++) { ! ProcGlobal->procSemMap[i].procSemId = (IpcSemaphoreId)-1; ProcGlobal->procSemMap[i].freeSemMap = 0; } *************** *** 170,175 **** --- 175,184 ---- */ for (i = 0; i < semMapEntries; i++) { + #ifdef HAVE_POSIX_IPC + ProcGlobal->procSemMap[i].procSemId = + IpcSemaphoreCreate(&ProcGlobal->procSemMap[i].procSemMem, true, 1, false); + #else IpcSemaphoreId semId; semId = IpcSemaphoreCreate(PROC_NSEMS_PER_SET, *************** *** 177,182 **** --- 186,192 ---- 1, false); ProcGlobal->procSemMap[i].procSemId = semId; + #endif } /* *************** *** 242,248 **** * Initialize all fields of MyProc. */ SHMQueueElemInit(&(MyProc->links)); ! MyProc->sem.semId = -1; /* no wait-semaphore acquired yet */ MyProc->sem.semNum = -1; MyProc->errType = STATUS_OK; MyProc->xid = InvalidTransactionId; --- 252,258 ---- * Initialize all fields of MyProc. */ SHMQueueElemInit(&(MyProc->links)); ! MyProc->sem.semId = (IpcSemaphoreId)-1; /* no wait-semaphore acquired yet */ MyProc->sem.semNum = -1; MyProc->errType = STATUS_OK; MyProc->xid = InvalidTransactionId; *************** *** 348,353 **** --- 358,390 ---- static void ZeroProcSemaphore(PROC *proc) { + #ifdef HAVE_POSIX_IPC + int errval; + + if (proc->sem.semId == (IpcSemaphoreId)-1) + return; + /* + there's no way to 'reset' value of POSIX semaphore after sem_init(). + So just roll it down to 0 using sem_trywait(). Hopefully, nobody + rolls it up at the same time... but either way we don't return until + it has reached 0, it might just take little longer ... + */ + while(1) + { + errval = sem_trywait(proc->sem.semId); + if (errval == -1 && errno != EINTR) break; + } + #ifdef EAGAIN + if (errno != EAGAIN) + #elif defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN)) + if (errno != EWOULDBLOCK) + #endif + { + fprintf(stderr, "ZeroProcSemaphore: sem_trywait(id=%p) failed: %s\n", + proc->sem.semId, strerror(errno)); + proc_exit(255); + } + #else union semun semun; semun.val = 0; *************** *** 357,362 **** --- 394,400 ---- proc->sem.semId, strerror(errno)); proc_exit(255); } + #endif } /* *************** *** 1115,1121 **** } } /* can't elog here!!! */ ! fprintf(stderr, "ProcFreeSem: no ProcGlobal entry for semId %d\n", semId); } /* --- 1153,1159 ---- } } /* can't elog here!!! */ ! fprintf(stderr, "ProcFreeSem: no ProcGlobal entry for semId %d\n", (int)semId); } /* diff -crP postgresql-7.2b2/src/backend/storage/lmgr/spin.c postgresql-7.2b2.patched/src/backend/storage/lmgr/spin.c *** postgresql-7.2b2/src/backend/storage/lmgr/spin.c Mon Nov 5 11:46:28 2001 --- postgresql-7.2b2.patched/src/backend/storage/lmgr/spin.c Mon Nov 19 21:21:17 2001 *************** *** 24,29 **** --- 24,32 ---- #include #include "storage/ipc.h" + + #ifndef HAVE_POSIX_IPC + /* In Ultrix, sem.h and shm.h must be included AFTER ipc.h */ #ifdef HAVE_SYS_SEM_H #include *************** *** 33,44 **** #include "port/darwin/sem.h" #endif #include "storage/lwlock.h" #include "storage/proc.h" #include "storage/spin.h" ! #ifdef HAS_TEST_AND_SET /* * CreateSpinlocks --- create and initialize spinlocks during startup --- 36,49 ---- #include "port/darwin/sem.h" #endif + #endif /* HAVE_POSIX_IPC */ + #include "storage/lwlock.h" #include "storage/proc.h" #include "storage/spin.h" ! #if defined(HAS_TEST_AND_SET) || defined(USE_PHTREAD_MUTEXES) || defined(USE_PTHREAD_SPINLOCKS) /* * CreateSpinlocks --- create and initialize spinlocks during startup *************** *** 124,133 **** --- 129,142 ---- /* Create sema sets and set all semas to count 1 */ for (i = 0; i < numSpinSets; i++) { + #ifdef HAVE_POSIX_IPC + SpinLockIds[i] = IpcSemaphoreCreate(NULL, false, 1, false); + #else SpinLockIds[i] = IpcSemaphoreCreate(SPINLOCKS_PER_SET, IPCProtection, 1, false); + #endif } /* Init counter for allocating dynamic spinlocks */ *************** *** 148,154 **** --- 157,170 ---- for (i = 0; i < numSpinSets; i++) { if (SpinLockIds[i] >= 0) + #ifdef HAVE_POSIX_IPC + { + IpcSemaphoreKill(SpinLockIds[i]); + free(SpinLockIds[i]); + } + #else IpcSemaphoreKill(SpinLockIds[i]); + #endif } free(SpinLockIds); SpinLockIds = NULL; diff -crP postgresql-7.2b2/src/backend/utils/misc/guc.c postgresql-7.2b2.patched/src/backend/utils/misc/guc.c *** postgresql-7.2b2/src/backend/utils/misc/guc.c Mon Oct 29 23:38:56 2001 --- postgresql-7.2b2.patched/src/backend/utils/misc/guc.c Thu Nov 8 13:52:18 2001 *************** *** 18,23 **** --- 18,29 ---- #include #include + #ifdef __QNXNTO__ + /* Some bozo has defined DBL_MAX as non-constant */ + #undef DBL_MAX + #define DBL_MAX 1.7976931348623157e+308 + #endif + #include "utils/guc.h" #include "access/xlog.h" diff -crP postgresql-7.2b2/src/backend/utils/sort/tuplesort.c postgresql-7.2b2.patched/src/backend/utils/sort/tuplesort.c *** postgresql-7.2b2/src/backend/utils/sort/tuplesort.c Sun Oct 28 01:25:57 2001 --- postgresql-7.2b2.patched/src/backend/utils/sort/tuplesort.c Thu Nov 15 02:16:19 2001 *************** *** 1882,1888 **** * otherwise the sort algorithm wouldn't have checked whether one must * appear before the other. */ ! if (state->enforceUnique && !equal_hasnull) elog(ERROR, "Cannot create unique index. Table contains non-unique values"); return 0; --- 1882,1888 ---- * otherwise the sort algorithm wouldn't have checked whether one must * appear before the other. */ ! if (state->enforceUnique && !equal_hasnull && tuple1 != tuple2) elog(ERROR, "Cannot create unique index. Table contains non-unique values"); return 0; diff -crP postgresql-7.2b2/src/include/port/qnx6.h postgresql-7.2b2.patched/src/include/port/qnx6.h *** postgresql-7.2b2/src/include/port/qnx6.h Wed Dec 31 18:00:00 1969 --- postgresql-7.2b2.patched/src/include/port/qnx6.h Mon Nov 19 20:51:46 2001 *************** *** 0 **** --- 1,81 ---- + #include /* for namser.h */ + #include /* for BYTE_ORDER */ + #include /* for unix.h */ + #include + #include /* for select */ + #include /* for NAN */ + + /* + Define type of locking implementation first. + USE_PTHREAD_MUTEXES is best on non-SMP + USE_PTHREAD_SPINLOCK is best on SMP, + unless there's assembler code for your platform (x86 & ARM) in which case + neither should be defined (HAS_TEST_AND_SET will be used then) + */ + + /* + 1. Figure if we have hardware TAS. + We want to have HAS_TESTAND_SET defined whenever possible to avoid extra tweaking of other files + */ + #if defined(__i386__) || defined(__arm__) + #define HAS_TEST_AND_SET + #endif + + /* + 2. Now make decision what to use, based on SMP_HARDWARE and HAS_TEST_AND_SET + Uncomment SMP_HARDWARE line for SMP machines. + */ + /* #define SMP_HARDWARE */ + #if defined(SMP_HARDWARE) + + #ifndef HAS_TEST_AND_SET + #define USE_PTHREAD_SPINLOCKS + #endif + + #else /* non SMP */ + + #define USE_PTHREAD_MUTEXES + + #endif + + /* + 3. Finally, include proper header and define lock datatype. + */ + #if defined(USE_PTHREAD_MUTEXES) + + #include + typedef pthread_mutex_t slock_t; + + #elif defined(USE_PTHREAD_SPINLOCKS) + + #include + typedef pthread_spinlock_t slock_t; + + #elif defined(HAS_TEST_AND_SET) + typedef unsigned char slock_t; + + #endif + + typedef unsigned short ushort; + + /* + If this is not defined, SysV IPC emulation will be needed. + I don't think emulation code is much more reliable or better tested. + But it certainly is slower and uglier, so this should probably be + always defined on QNX, unless you see some problem with locking. + */ + #define HAVE_POSIX_IPC + + #define HAVE_STRING_H + + /* + Those are workarounds for bugs in 6.1 (hopefully not needed for 6.1.1) + */ + #ifndef NAN + #define NAN (*(const double *) &_Nan) + #endif /* NAN */ + + #if (_NTO_VERSION <= 610) + #undef MAXIMUM_ALIGNOF + #define MAXIMUM_ALIGNOF (sizeof(int)) + #endif diff -crP postgresql-7.2b2/src/include/storage/ipc.h postgresql-7.2b2.patched/src/include/storage/ipc.h *** postgresql-7.2b2/src/include/storage/ipc.h Mon Nov 5 11:46:35 2001 --- postgresql-7.2b2.patched/src/include/storage/ipc.h Sun Nov 18 00:07:04 2001 *************** *** 19,24 **** --- 19,33 ---- #define IPC_H #include + + #ifdef HAVE_POSIX_IPC + #include + #include + + typedef sem_t * IpcSemaphoreId; + + #else /* no POSIX_IPC */ + #ifdef HAVE_SYS_IPC_H #include #endif /* HAVE_SYS_IPC_H */ *************** *** 30,61 **** struct semid_ds *buf; unsigned short *array; }; ! #endif ! /* generic IPC definitions */ ! #define IPCProtection (0600) /* access/modify by user only */ /* semaphore definitions */ - typedef uint32 IpcSemaphoreKey; /* semaphore key passed to semget(2) */ typedef int IpcSemaphoreId; /* semaphore ID returned by semget(2) */ ! #define IPC_NMAXSEM 32 /* maximum number of semaphores per semID */ ! ! #define PGSemaMagic 537 /* must be less than SEMVMX */ /* shared memory definitions */ typedef uint32 IpcMemoryKey; /* shared memory key passed to shmget(2) */ typedef int IpcMemoryId; /* shared memory ID returned by shmget(2) */ typedef struct PGShmemHeader /* standard header for all Postgres shmem */ { int32 magic; /* magic # to identify Postgres segments */ #define PGShmemMagic 679834892 pid_t creatorPID; /* PID of creating process */ uint32 totalsize; /* total size of segment */ uint32 freeoffset; /* offset to first free space */ } PGShmemHeader; --- 39,73 ---- struct semid_ds *buf; unsigned short *array; }; ! #endif /* HAVE_UNION_SEMUN */ /* generic IPC definitions */ ! #define PGSemaMagic 537 /* must be less than SEMVMX */ ! #define IPC_NMAXSEM 32 /* maximum number of semaphores per semID */ ! ! typedef uint32 IpcSemaphoreKey; /* semaphore key passed to semget(2) */ /* semaphore definitions */ typedef int IpcSemaphoreId; /* semaphore ID returned by semget(2) */ ! #endif /* POSIX IPC */ /* shared memory definitions */ + #define IPCProtection (0600) /* access/modify by user only */ + typedef uint32 IpcMemoryKey; /* shared memory key passed to shmget(2) */ typedef int IpcMemoryId; /* shared memory ID returned by shmget(2) */ typedef struct PGShmemHeader /* standard header for all Postgres shmem */ { + #ifndef HAVE_POSIX_IPC int32 magic; /* magic # to identify Postgres segments */ #define PGShmemMagic 679834892 pid_t creatorPID; /* PID of creating process */ + #endif uint32 totalsize; /* total size of segment */ uint32 freeoffset; /* offset to first free space */ } PGShmemHeader; *************** *** 72,80 **** --- 84,98 ---- extern void IpcInitKeyAssignment(int port); + #ifdef HAVE_POSIX_IPC + extern IpcSemaphoreId IpcSemaphoreCreate(void *storage, bool shared, + int semStartValue, + bool removeOnExit); + #else extern IpcSemaphoreId IpcSemaphoreCreate(int numSems, int permission, int semStartValue, bool removeOnExit); + #endif extern void IpcSemaphoreKill(IpcSemaphoreId semId); extern void IpcSemaphoreLock(IpcSemaphoreId semId, int sem, bool interruptOK); extern void IpcSemaphoreUnlock(IpcSemaphoreId semId, int sem); diff -crP postgresql-7.2b2/src/include/storage/proc.h postgresql-7.2b2.patched/src/include/storage/proc.h *** postgresql-7.2b2/src/include/storage/proc.h Mon Nov 5 18:38:26 2001 --- postgresql-7.2b2.patched/src/include/storage/proc.h Sat Nov 17 22:54:01 2001 *************** *** 22,29 **** typedef struct { ! IpcSemaphoreId semId; /* SysV semaphore set ID */ ! int semNum; /* semaphore number within set */ } SEMA; /* --- 22,29 ---- typedef struct { ! IpcSemaphoreId semId; /* semaphore id */ ! int semNum; /* semaphore number within SysV set */ } SEMA; /* *************** *** 97,111 **** * semaphore (see storage/lmgr/proc.c), so the computation may look wrong, * but it's right. */ #define PROC_NSEMS_PER_SET 16 #define PROC_SEM_MAP_ENTRIES(maxBackends) ((maxBackends)/PROC_NSEMS_PER_SET+1) typedef struct { /* info about a single set of per-process semaphores */ ! IpcSemaphoreId procSemId; ! int32 freeSemMap; ! /* * In freeSemMap, bit i is set if the i'th semaphore of this sema set * is allocated to a process. (i counts from 0 at the LSB) --- 97,117 ---- * semaphore (see storage/lmgr/proc.c), so the computation may look wrong, * but it's right. */ + #ifdef HAVE_POSIX_IPC /* No 'sets' in POSIX */ + #define PROC_NSEMS_PER_SET 1 + #else #define PROC_NSEMS_PER_SET 16 + #endif #define PROC_SEM_MAP_ENTRIES(maxBackends) ((maxBackends)/PROC_NSEMS_PER_SET+1) typedef struct { /* info about a single set of per-process semaphores */ ! IpcSemaphoreId procSemId; ! int32 freeSemMap; ! #ifdef HAVE_POSIX_IPC ! sem_t procSemMem; ! #endif /* * In freeSemMap, bit i is set if the i'th semaphore of this sema set * is allocated to a process. (i counts from 0 at the LSB) diff -crP postgresql-7.2b2/src/include/storage/s_lock.h postgresql-7.2b2.patched/src/include/storage/s_lock.h *** postgresql-7.2b2/src/include/storage/s_lock.h Fri Sep 28 23:02:26 2001 --- postgresql-7.2b2.patched/src/include/storage/s_lock.h Mon Nov 19 19:49:04 2001 *************** *** 1,3 **** --- 1,4 ---- + /*------------------------------------------------------------------------- * * s_lock.h *************** *** 67,75 **** #include "storage/ipc.h" ! #if defined(HAS_TEST_AND_SET) #if defined(__GNUC__) /************************************************************************* --- 68,119 ---- #include "storage/ipc.h" + #if defined(USE_PTHREAD_MUTEXES) + /* + * Mutexes are better choice when OS has very fast context switches + * (i.e., overhead of a system call is negligibly small compared to overhead + * of scheduler) AND we're running on single-CPU system. + * Currently defined on QNX6 but it is portable and might be useful for + * other platforms. + * + * Note that slock_t is assumed to be defined as pthread_mutex_t. + * + * Implementation of S_LOCK_FREE() is not very efficient, but it is + * only used by test program anyway. + */ + #define TAS(lock) (pthread_mutex_trylock((lock)) != EOK) + #define S_LOCK(lock) pthread_mutex_lock((lock)) + #define S_UNLOCK(lock) pthread_mutex_unlock((lock)) + #define S_INIT_LOCK(lock) pthread_mutex_init((lock), NULL) + #define S_LOCK_FREE(lock) ((pthread_mutex_trylock((lock)) == EOK) ? (pthread_mutex_unlock(lock) == EOK) : 0) ! #elif defined(USE_PTHREAD_SPINLOCKS) ! /* ! * Spinlocks are better choice when we run on SMP system. Performance probably ! * would be better using hardware TAS, but this should be portable between ! * OSes and hardware (as per POSIX 1003.1j draft). ! * If hardware does not support TAS, there's still good chance this will ! * be more efficient than using SysV semaphores, assuming OS vendor has done ! * any decent job implementing PTHREADS library. ! * ! * It probably does not make sense to use this if hardware supports TAS and ! * there's assembler implementation for your platform below. It was added ! * to avoid messing with ugly SysV semaphores when running on non-i386 ! * SMP platforms (PPC could be real possibility). Currently defined on QNX6. ! * ! * Note that slock_t is assumed to be defined as pthread_spinlock_t. ! * ! * Implementation of S_LOCK_FREE() is not very efficient, but it is ! * only used by test program anyway. ! */ ! ! #define TAS(lock) (pthread_spin_trylock((lock)) != EOK) ! #define S_LOCK(lock) pthread_spin_lock((lock)) ! #define S_UNLOCK(lock) pthread_spin_unlock((lock)) ! #define S_INIT_LOCK(lock) pthread_spin_init((lock), NULL) ! #define S_LOCK_FREE(lock) ((pthread_spin_trylock((lock)) == EOK) ? (pthread_mutex_unlock(lock) == EOK) : 0) + #elif defined(HAS_TEST_AND_SET) #if defined(__GNUC__) /************************************************************************* *************** *** 392,398 **** value [al]; #endif /* __QNX__ and __WATCOMC__*/ - #if defined(__sgi) /* --- 436,441 ---- diff -crP postgresql-7.2b2/src/makefiles/Makefile.qnx6 postgresql-7.2b2.patched/src/makefiles/Makefile.qnx6 *** postgresql-7.2b2/src/makefiles/Makefile.qnx6 Wed Dec 31 18:00:00 1969 --- postgresql-7.2b2.patched/src/makefiles/Makefile.qnx6 Sat Dec 16 12:14:25 2000 *************** *** 0 **** --- 1,9 ---- + AROPT = crs + export_dynamic = -export-dynamic + rpath = -Wl,-rpath,$(libdir) + shlib_symbolic = -Wl,-Bsymbolic + DLSUFFIX = .so + CFLAGS_SL = -fpic + + %.so: %.o + $(CC) -shared -o $@ $< diff -crP postgresql-7.2b2/src/template/qnx6 postgresql-7.2b2.patched/src/template/qnx6 *** postgresql-7.2b2/src/template/qnx6 Wed Dec 31 18:00:00 1969 --- postgresql-7.2b2.patched/src/template/qnx6 Tue Nov 6 12:21:28 2001 *************** *** 0 **** --- 1,2 ---- + CFLAGS= + LIBS= diff -crP postgresql-7.2b2/src/test/regress/expected/alter_table.out postgresql-7.2b2.patched/src/test/regress/expected/alter_table.out *** postgresql-7.2b2/src/test/regress/expected/alter_table.out Sat Nov 3 21:08:11 2001 --- postgresql-7.2b2.patched/src/test/regress/expected/alter_table.out Sun Nov 18 01:08:29 2001 *************** *** 471,477 **** insert into atacc1 (test) values (2); -- add a unique constraint (fails) alter table atacc1 add constraint atacc_test1 unique (test); ! NOTICE: ALTER TABLE / ADD UNIQUE will create implicit index 'atacc_test1' for table 'atacc1' ERROR: Cannot create unique index. Table contains non-unique values insert into atacc1 (test) values (3); drop table atacc1; --- 471,477 ---- insert into atacc1 (test) values (2); -- add a unique constraint (fails) alter table atacc1 add constraint atacc_test1 unique (test); ! NOTICE: ALTER TABLE / ADD UNIQUE will create implicit index 'atacc_test1' for table 'atacc1' ERROR: Cannot create unique index. Table contains non-unique values insert into atacc1 (test) values (3); drop table atacc1; diff -crP postgresql-7.2b2/src/test/regress/expected/geometry-x86-pc-nto-qnx.out postgresql-7.2b2.patched/src/test/regress/expected/geometry-x86-pc-nto-qnx.out *** postgresql-7.2b2/src/test/regress/expected/geometry-x86-pc-nto-qnx.out Wed Dec 31 18:00:00 1969 --- postgresql-7.2b2.patched/src/test/regress/expected/geometry-x86-pc-nto-qnx.out Sun Nov 18 01:04:25 2001 *************** *** 0 **** --- 1,532 ---- + -- + -- GEOMETRY + -- + -- + -- Points + -- + SELECT '' AS four, center(f1) AS center + FROM BOX_TBL; + four | center + ------+--------- + | (1,1) + | (2,2) + | (2.5,3) + | (3,3) + (4 rows) + + SELECT '' AS four, (@@ f1) AS center + FROM BOX_TBL; + four | center + ------+--------- + | (1,1) + | (2,2) + | (2.5,3) + | (3,3) + (4 rows) + + SELECT '' AS six, point(f1) AS center + FROM CIRCLE_TBL; + six | center + -----+----------- + | (0,0) + | (1,2) + | (1,3) + | (1,2) + | (100,200) + | (100,0) + (6 rows) + + SELECT '' AS six, (@@ f1) AS center + FROM CIRCLE_TBL; + six | center + -----+----------- + | (0,0) + | (1,2) + | (1,3) + | (1,2) + | (100,200) + | (100,0) + (6 rows) + + SELECT '' AS two, (@@ f1) AS center + FROM POLYGON_TBL + WHERE (# f1) > 2; + two | center + -----+------------------------------------- + | (1.33333333333333,1.33333333333333) + | (2.33333333333333,1.33333333333333) + (2 rows) + + -- "is horizontal" function + SELECT '' AS two, p1.f1 + FROM POINT_TBL p1 + WHERE ishorizontal(p1.f1, point '(0,0)'); + two | f1 + -----+--------- + | (0,0) + | (-10,0) + (2 rows) + + -- "is horizontal" operator + SELECT '' AS two, p1.f1 + FROM POINT_TBL p1 + WHERE p1.f1 ?- point '(0,0)'; + two | f1 + -----+--------- + | (0,0) + | (-10,0) + (2 rows) + + -- "is vertical" function + SELECT '' AS one, p1.f1 + FROM POINT_TBL p1 + WHERE isvertical(p1.f1, point '(5.1,34.5)'); + one | f1 + -----+------------ + | (5.1,34.5) + (1 row) + + -- "is vertical" operator + SELECT '' AS one, p1.f1 + FROM POINT_TBL p1 + WHERE p1.f1 ?| point '(5.1,34.5)'; + one | f1 + -----+------------ + | (5.1,34.5) + (1 row) + + -- + -- Line segments + -- + -- intersection + SELECT '' AS count, p.f1, l.s, l.s # p.f1 AS intersection + FROM LSEG_TBL l, POINT_TBL p; + ERROR: Unable to identify an operator '#' for types 'lseg' and 'point' + You will have to retype this query using an explicit cast + -- closest point + SELECT '' AS thirty, p.f1, l.s, p.f1 ## l.s AS closest + FROM LSEG_TBL l, POINT_TBL p; + thirty | f1 | s | closest + --------+------------+-------------------------------+--------------------------------------- + | (0,0) | [(1,2),(3,4)] | (1,2) + | (-10,0) | [(1,2),(3,4)] | (1,2) + | (-3,4) | [(1,2),(3,4)] | (1,2) + | (5.1,34.5) | [(1,2),(3,4)] | (3,4) + | (-5,-12) | [(1,2),(3,4)] | (1,2) + | (10,10) | [(1,2),(3,4)] | (3,4) + | (0,0) | [(0,0),(6,6)] | (-0,0) + | (-10,0) | [(0,0),(6,6)] | (0,0) + | (-3,4) | [(0,0),(6,6)] | (0.5,0.5) + | (5.1,34.5) | [(0,0),(6,6)] | (6,6) + | (-5,-12) | [(0,0),(6,6)] | (0,0) + | (10,10) | [(0,0),(6,6)] | (6,6) + | (0,0) | [(10,-10),(-3,-4)] | (-2.04878048780488,-4.4390243902439) + | (-10,0) | [(10,-10),(-3,-4)] | (-3,-4) + | (-3,4) | [(10,-10),(-3,-4)] | (-3,-4) + | (5.1,34.5) | [(10,-10),(-3,-4)] | (-3,-4) + | (-5,-12) | [(10,-10),(-3,-4)] | (-1.60487804878049,-4.64390243902439) + | (10,10) | [(10,-10),(-3,-4)] | (2.39024390243902,-6.48780487804878) + | (0,0) | [(-1000000,200),(300000,-40)] | (0.0028402365895872,15.384614860264) + | (-10,0) | [(-1000000,200),(300000,-40)] | (-9.99715942258202,15.3864610140473) + | (-3,4) | [(-1000000,200),(300000,-40)] | (-2.99789812267519,15.3851688427303) + | (5.1,34.5) | [(-1000000,200),(300000,-40)] | (5.09647083221496,15.3836744976925) + | (-5,-12) | [(-1000000,200),(300000,-40)] | (-4.99494420845634,15.3855375281616) + | (10,10) | [(-1000000,200),(300000,-40)] | (10.000993741978,15.3827690473092) + | (0,0) | [(11,22),(33,44)] | (11,22) + | (-10,0) | [(11,22),(33,44)] | (11,22) + | (-3,4) | [(11,22),(33,44)] | (11,22) + | (5.1,34.5) | [(11,22),(33,44)] | (14.3,25.3) + | (-5,-12) | [(11,22),(33,44)] | (11,22) + | (10,10) | [(11,22),(33,44)] | (11,22) + (30 rows) + + -- + -- Lines + -- + -- + -- Boxes + -- + SELECT '' as six, box(f1) AS box FROM CIRCLE_TBL; + six | box + -----+---------------------------------------------------------------------------- + | (2.12132034355964,2.12132034355964),(-2.12132034355964,-2.12132034355964) + | (71.7106781186547,72.7106781186547),(-69.7106781186547,-68.7106781186547) + | (4.53553390593274,6.53553390593274),(-2.53553390593274,-0.535533905932737) + | (3.12132034355964,4.12132034355964),(-1.12132034355964,-0.121320343559642) + | (107.071067811865,207.071067811865),(92.9289321881345,192.928932188135) + | (170.710678118655,70.7106781186547),(29.2893218813453,-70.7106781186547) + (6 rows) + + -- translation + SELECT '' AS twentyfour, b.f1 + p.f1 AS translation + FROM BOX_TBL b, POINT_TBL p; + twentyfour | translation + ------------+------------------------- + | (2,2),(0,0) + | (-8,2),(-10,0) + | (-1,6),(-3,4) + | (7.1,36.5),(5.1,34.5) + | (-3,-10),(-5,-12) + | (12,12),(10,10) + | (3,3),(1,1) + | (-7,3),(-9,1) + | (0,7),(-2,5) + | (8.1,37.5),(6.1,35.5) + | (-2,-9),(-4,-11) + | (13,13),(11,11) + | (2.5,3.5),(2.5,2.5) + | (-7.5,3.5),(-7.5,2.5) + | (-0.5,7.5),(-0.5,6.5) + | (7.6,38),(7.6,37) + | (-2.5,-8.5),(-2.5,-9.5) + | (12.5,13.5),(12.5,12.5) + | (3,3),(3,3) + | (-7,3),(-7,3) + | (0,7),(0,7) + | (8.1,37.5),(8.1,37.5) + | (-2,-9),(-2,-9) + | (13,13),(13,13) + (24 rows) + + SELECT '' AS twentyfour, b.f1 - p.f1 AS translation + FROM BOX_TBL b, POINT_TBL p; + twentyfour | translation + ------------+--------------------------- + | (2,2),(0,0) + | (12,2),(10,0) + | (5,-2),(3,-4) + | (-3.1,-32.5),(-5.1,-34.5) + | (7,14),(5,12) + | (-8,-8),(-10,-10) + | (3,3),(1,1) + | (13,3),(11,1) + | (6,-1),(4,-3) + | (-2.1,-31.5),(-4.1,-33.5) + | (8,15),(6,13) + | (-7,-7),(-9,-9) + | (2.5,3.5),(2.5,2.5) + | (12.5,3.5),(12.5,2.5) + | (5.5,-0.5),(5.5,-1.5) + | (-2.6,-31),(-2.6,-32) + | (7.5,15.5),(7.5,14.5) + | (-7.5,-6.5),(-7.5,-7.5) + | (3,3),(3,3) + | (13,3),(13,3) + | (6,-1),(6,-1) + | (-2.1,-31.5),(-2.1,-31.5) + | (8,15),(8,15) + | (-7,-7),(-7,-7) + (24 rows) + + -- scaling and rotation + SELECT '' AS twentyfour, b.f1 * p.f1 AS rotation + FROM BOX_TBL b, POINT_TBL p; + twentyfour | rotation + ------------+----------------------------- + | (0,0),(0,0) + | (-0,0),(-20,-20) + | (-0,2),(-14,0) + | (0,79.2),(-58.8,0) + | (14,-0),(0,-34) + | (0,40),(0,0) + | (0,0),(0,0) + | (-10,-10),(-30,-30) + | (-7,3),(-21,1) + | (-29.4,118.8),(-88.2,39.6) + | (21,-17),(7,-51) + | (0,60),(0,20) + | (0,0),(0,0) + | (-25,-25),(-25,-35) + | (-17.5,2.5),(-21.5,-0.5) + | (-73.5,104.1),(-108,99) + | (29.5,-42.5),(17.5,-47.5) + | (0,60),(-10,50) + | (0,0),(0,0) + | (-30,-30),(-30,-30) + | (-21,3),(-21,3) + | (-88.2,118.8),(-88.2,118.8) + | (21,-51),(21,-51) + | (0,60),(0,60) + (24 rows) + + SELECT '' AS twenty, b.f1 / p.f1 AS rotation + FROM BOX_TBL b, POINT_TBL p + WHERE (p.f1 <-> point '(0,0)') >= 1; + twenty | rotation + --------+----------------------------------------------------------------------------------- + | (0,-0),(-0.2,-0.2) + | (-0.1,-0.1),(-0.3,-0.3) + | (-0.25,-0.25),(-0.25,-0.35) + | (-0.3,-0.3),(-0.3,-0.3) + | (0.08,-0),(0,-0.56) + | (0.12,-0.28),(0.04,-0.84) + | (0.26,-0.7),(0.1,-0.82) + | (0.12,-0.84),(0.12,-0.84) + | (0.0651176557643925,0),(0,-0.0483449262493217) + | (0.0976764836465887,-0.0241724631246608),(0.0325588278821962,-0.0725173893739825) + | (0.109762715208919,-0.0562379754328844),(0.0813970697054906,-0.0604311578116521) + | (0.0976764836465887,-0.0725173893739825),(0.0976764836465887,-0.0725173893739825) + | (-0,0.0828402366863905),(-0.201183431952663,0) + | (-0.100591715976331,0.124260355029586),(-0.301775147928994,0.0414201183431953) + | (-0.251479289940828,0.103550295857988),(-0.322485207100592,0.0739644970414201) + | (-0.301775147928994,0.124260355029586),(-0.301775147928994,0.124260355029586) + | (0.2,0),(0,0) + | (0.3,0),(0.1,0) + | (0.3,0.05),(0.25,0) + | (0.3,0),(0.3,0) + (20 rows) + + -- + -- Paths + -- + SET geqo TO 'off'; + SELECT '' AS eight, npoints(f1) AS npoints, f1 AS path FROM PATH_TBL; + eight | npoints | path + -------+---------+--------------------------- + | 2 | [(1,2),(3,4)] + | 2 | ((1,2),(3,4)) + | 4 | [(0,0),(3,0),(4,5),(1,6)] + | 2 | ((1,2),(3,4)) + | 2 | ((1,2),(3,4)) + | 2 | [(1,2),(3,4)] + | 2 | [(11,12),(13,14)] + | 2 | ((11,12),(13,14)) + (8 rows) + + SELECT '' AS four, path(f1) FROM POLYGON_TBL; + four | path + ------+--------------------- + | ((2,0),(2,4),(0,0)) + | ((3,1),(3,3),(1,0)) + | ((0,0)) + | ((0,1),(0,1)) + (4 rows) + + -- translation + SELECT '' AS eight, p1.f1 + point '(10,10)' AS dist_add + FROM PATH_TBL p1; + eight | dist_add + -------+----------------------------------- + | [(11,12),(13,14)] + | ((11,12),(13,14)) + | [(10,10),(13,10),(14,15),(11,16)] + | ((11,12),(13,14)) + | ((11,12),(13,14)) + | [(11,12),(13,14)] + | [(21,22),(23,24)] + | ((21,22),(23,24)) + (8 rows) + + -- scaling and rotation + SELECT '' AS eight, p1.f1 * point '(2,-1)' AS dist_mul + FROM PATH_TBL p1; + eight | dist_mul + -------+------------------------------ + | [(4,3),(10,5)] + | ((4,3),(10,5)) + | [(0,0),(6,-3),(13,6),(8,11)] + | ((4,3),(10,5)) + | ((4,3),(10,5)) + | [(4,3),(10,5)] + | [(34,13),(40,15)] + | ((34,13),(40,15)) + (8 rows) + + RESET geqo; + -- + -- Polygons + -- + -- containment + SELECT '' AS twentyfour, p.f1, poly.f1, poly.f1 ~ p.f1 AS contains + FROM POLYGON_TBL poly, POINT_TBL p; + twentyfour | f1 | f1 | contains + ------------+------------+---------------------+---------- + | (0,0) | ((2,0),(2,4),(0,0)) | t + | (-10,0) | ((2,0),(2,4),(0,0)) | f + | (-3,4) | ((2,0),(2,4),(0,0)) | f + | (5.1,34.5) | ((2,0),(2,4),(0,0)) | f + | (-5,-12) | ((2,0),(2,4),(0,0)) | f + | (10,10) | ((2,0),(2,4),(0,0)) | f + | (0,0) | ((3,1),(3,3),(1,0)) | f + | (-10,0) | ((3,1),(3,3),(1,0)) | f + | (-3,4) | ((3,1),(3,3),(1,0)) | f + | (5.1,34.5) | ((3,1),(3,3),(1,0)) | f + | (-5,-12) | ((3,1),(3,3),(1,0)) | f + | (10,10) | ((3,1),(3,3),(1,0)) | f + | (0,0) | ((0,0)) | t + | (-10,0) | ((0,0)) | f + | (-3,4) | ((0,0)) | f + | (5.1,34.5) | ((0,0)) | f + | (-5,-12) | ((0,0)) | f + | (10,10) | ((0,0)) | f + | (0,0) | ((0,1),(0,1)) | f + | (-10,0) | ((0,1),(0,1)) | f + | (-3,4) | ((0,1),(0,1)) | f + | (5.1,34.5) | ((0,1),(0,1)) | f + | (-5,-12) | ((0,1),(0,1)) | f + | (10,10) | ((0,1),(0,1)) | f + (24 rows) + + SELECT '' AS twentyfour, p.f1, poly.f1, p.f1 @ poly.f1 AS contained + FROM POLYGON_TBL poly, POINT_TBL p; + twentyfour | f1 | f1 | contained + ------------+------------+---------------------+----------- + | (0,0) | ((2,0),(2,4),(0,0)) | t + | (-10,0) | ((2,0),(2,4),(0,0)) | f + | (-3,4) | ((2,0),(2,4),(0,0)) | f + | (5.1,34.5) | ((2,0),(2,4),(0,0)) | f + | (-5,-12) | ((2,0),(2,4),(0,0)) | f + | (10,10) | ((2,0),(2,4),(0,0)) | f + | (0,0) | ((3,1),(3,3),(1,0)) | f + | (-10,0) | ((3,1),(3,3),(1,0)) | f + | (-3,4) | ((3,1),(3,3),(1,0)) | f + | (5.1,34.5) | ((3,1),(3,3),(1,0)) | f + | (-5,-12) | ((3,1),(3,3),(1,0)) | f + | (10,10) | ((3,1),(3,3),(1,0)) | f + | (0,0) | ((0,0)) | t + | (-10,0) | ((0,0)) | f + | (-3,4) | ((0,0)) | f + | (5.1,34.5) | ((0,0)) | f + | (-5,-12) | ((0,0)) | f + | (10,10) | ((0,0)) | f + | (0,0) | ((0,1),(0,1)) | f + | (-10,0) | ((0,1),(0,1)) | f + | (-3,4) | ((0,1),(0,1)) | f + | (5.1,34.5) | ((0,1),(0,1)) | f + | (-5,-12) | ((0,1),(0,1)) | f + | (10,10) | ((0,1),(0,1)) | f + (24 rows) + + SELECT '' AS four, npoints(f1) AS npoints, f1 AS polygon + FROM POLYGON_TBL; + four | npoints | polygon + ------+---------+--------------------- + | 3 | ((2,0),(2,4),(0,0)) + | 3 | ((3,1),(3,3),(1,0)) + | 1 | ((0,0)) + | 2 | ((0,1),(0,1)) + (4 rows) + + SELECT '' AS four, polygon(f1) + FROM BOX_TBL; + four | polygon + ------+------------------------------------------- + | ((0,0),(0,2),(2,2),(2,0)) + | ((1,1),(1,3),(3,3),(3,1)) + | ((2.5,2.5),(2.5,3.5),(2.5,3.5),(2.5,2.5)) + | ((3,3),(3,3),(3,3),(3,3)) + (4 rows) + + SELECT '' AS four, polygon(f1) + FROM PATH_TBL WHERE isclosed(f1); + four | polygon + ------+------------------- + | ((1,2),(3,4)) + | ((1,2),(3,4)) + | ((1,2),(3,4)) + | ((11,12),(13,14)) + (4 rows) + + SELECT '' AS four, f1 AS open_path, polygon( pclose(f1)) AS polygon + FROM PATH_TBL + WHERE isopen(f1); + four | open_path | polygon + ------+---------------------------+--------------------------- + | [(1,2),(3,4)] | ((1,2),(3,4)) + | [(0,0),(3,0),(4,5),(1,6)] | ((0,0),(3,0),(4,5),(1,6)) + | [(1,2),(3,4)] | ((1,2),(3,4)) + | [(11,12),(13,14)] | ((11,12),(13,14)) + (4 rows) + + -- convert circles to polygons using the default number of points + SELECT '' AS six, polygon(f1) + FROM CIRCLE_TBL; + six | polygon + -----+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + | ((-3,0),(-2.59807621135076,1.50000000000442),(-1.49999999999116,2.59807621135842),(1.53102359018026e-11,3),(1.50000000001768,2.59807621134311),(2.59807621136607,1.4999999999779),(3,-3.06204718036052e-11),(2.59807621133545,-1.50000000003094),(1.49999999996464,-2.59807621137373),(-4.59307077054077e-11,-3),(-1.5000000000442,-2.5980762113278),(-2.59807621138139,-1.49999999995138)) + | ((-99,2),(-85.6025403783588,52.0000000001473),(-48.9999999997054,88.602540378614),(1.00000000051034,102),(51.0000000005893,88.6025403781037),(87.6025403788692,51.9999999992634),(101,1.99999999897932),(87.6025403778485,-48.0000000010313),(50.9999999988214,-84.6025403791243),(0.999999998468976,-98),(-49.0000000014732,-84.6025403775933),(-85.6025403793795,-47.9999999983794)) + | ((-4,3),(-3.33012701891794,5.50000000000737),(-1.49999999998527,7.3301270189307),(1.00000000002552,8),(3.50000000002946,7.33012701890518),(5.33012701894346,5.49999999996317),(6,2.99999999994897),(5.33012701889242,0.499999999948437),(3.49999999994107,-1.33012701895622),(0.999999999923449,-2),(-1.50000000007366,-1.33012701887967),(-3.33012701896897,0.500000000081028)) + | ((-2,2),(-1.59807621135076,3.50000000000442),(-0.499999999991161,4.59807621135842),(1.00000000001531,5),(2.50000000001768,4.59807621134311),(3.59807621136607,3.4999999999779),(4,1.99999999996938),(3.59807621133545,0.499999999969062),(2.49999999996464,-0.59807621137373),(0.999999999954069,-1),(-0.500000000044197,-0.598076211327799),(-1.59807621138139,0.500000000048617)) + | ((90,200),(91.3397459621641,205.000000000015),(95.0000000000295,208.660254037861),(100.000000000051,210),(105.000000000059,208.66025403781),(108.660254037887,204.999999999926),(110,199.999999999898),(108.660254037785,194.999999999897),(104.999999999882,191.339745962088),(99.9999999998469,190),(94.9999999998527,191.339745962241),(91.3397459620621,195.000000000162)) + | ((0,0),(13.3974596216412,50.0000000001473),(50.0000000002946,86.602540378614),(100.00000000051,100),(150.000000000589,86.6025403781037),(186.602540378869,49.9999999992634),(200,-1.02068239345351e-09),(186.602540377848,-50.0000000010313),(149.999999998821,-86.6025403791243),(99.999999998469,-100),(49.9999999985268,-86.6025403775933),(13.3974596206205,-49.9999999983794)) + (6 rows) + + -- convert the circle to an 8-point polygon + SELECT '' AS six, polygon(8, f1) + FROM CIRCLE_TBL; + six | polygon + -----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + | ((-3,0),(-2.12132034355423,2.12132034356506),(1.53102359018026e-11,3),(2.12132034357588,2.1213203435434),(3,-3.06204718036052e-11),(2.12132034353258,-2.12132034358671),(-4.59307077054077e-11,-3),(-2.12132034359753,-2.12132034352175)) + | ((-99,2),(-69.7106781184743,72.7106781188352),(1.00000000051034,102),(71.7106781191961,72.7106781181135),(101,1.99999999897932),(71.7106781177526,-68.7106781195569),(0.999999998468976,-98),(-69.7106781199178,-68.7106781173917)) + | ((-4,3),(-2.53553390592372,6.53553390594176),(1.00000000002552,8),(4.5355339059598,6.53553390590567),(6,2.99999999994897),(4.53553390588763,-0.535533905977846),(0.999999999923449,-2),(-2.53553390599589,-0.535533905869586)) + | ((-2,2),(-1.12132034355423,4.12132034356506),(1.00000000001531,5),(3.12132034357588,4.1213203435434),(4,1.99999999996938),(3.12132034353258,-0.121320343586708),(0.999999999954069,-1),(-1.12132034359753,-0.121320343521752)) + | ((90,200),(92.9289321881526,207.071067811884),(100.000000000051,210),(107.07106781192,207.071067811811),(110,199.999999999898),(107.071067811775,192.928932188044),(99.9999999998469,190),(92.9289321880082,192.928932188261)) + | ((0,0),(29.2893218815257,70.7106781188352),(100.00000000051,100),(170.710678119196,70.7106781181135),(200,-1.02068239345351e-09),(170.710678117753,-70.7106781195569),(99.999999998469,-100),(29.2893218800822,-70.7106781173917)) + (6 rows) + + -- + -- Circles + -- + SELECT '' AS six, circle(f1, 50.0) + FROM POINT_TBL; + six | circle + -----+----------------- + | <(0,0),50> + | <(-10,0),50> + | <(-3,4),50> + | <(5.1,34.5),50> + | <(-5,-12),50> + | <(10,10),50> + (6 rows) + + SELECT '' AS four, circle(f1) + FROM BOX_TBL; + four | circle + ------+------------------------- + | <(1,1),1.4142135623731> + | <(2,2),1.4142135623731> + | <(2.5,3),0.5> + | <(3,3),0> + (4 rows) + + SELECT '' AS two, circle(f1) + FROM POLYGON_TBL + WHERE (# f1) >= 3; + two | circle + -----+-------------------------------------------------------- + | <(1.33333333333333,1.33333333333333),2.04168905063636> + | <(2.33333333333333,1.33333333333333),1.47534300379185> + (2 rows) + + SELECT '' AS twentyfour, c1.f1 AS circle, p1.f1 AS point, (p1.f1 <-> c1.f1) AS distance + FROM CIRCLE_TBL c1, POINT_TBL p1 + WHERE (p1.f1 <-> c1.f1) > 0 + ORDER BY distance, circle, point using <<; + twentyfour | circle | point | distance + ------------+----------------+------------+------------------ + | <(100,0),100> | (5.1,34.5) | 0.97653192697797 + | <(1,2),3> | (-3,4) | 1.47213595499958 + | <(0,0),3> | (-3,4) | 2 + | <(100,0),100> | (-3,4) | 3.07764064044152 + | <(100,0),100> | (-5,-12) | 5.68348972285122 + | <(1,3),5> | (-10,0) | 6.40175425099138 + | <(1,3),5> | (10,10) | 6.40175425099138 + | <(0,0),3> | (-10,0) | 7 + | <(1,2),3> | (-10,0) | 8.18033988749895 + | <(1,2),3> | (10,10) | 9.0415945787923 + | <(0,0),3> | (-5,-12) | 10 + | <(100,0),100> | (-10,0) | 10 + | <(0,0),3> | (10,10) | 11.142135623731 + | <(1,3),5> | (-5,-12) | 11.1554944214035 + | <(1,2),3> | (-5,-12) | 12.2315462117278 + | <(1,3),5> | (5.1,34.5) | 26.7657047773224 + | <(1,2),3> | (5.1,34.5) | 29.757594539282 + | <(0,0),3> | (5.1,34.5) | 31.8749193547455 + | <(100,200),10> | (5.1,34.5) | 180.778038568384 + | <(100,200),10> | (10,10) | 200.237960416286 + | <(100,200),10> | (-3,4) | 211.415898254845 + | <(100,200),10> | (0,0) | 213.606797749979 + | <(100,200),10> | (-10,0) | 218.254244210267 + | <(100,200),10> | (-5,-12) | 226.577682802077 + (24 rows) + diff -crP postgresql-7.2b2/src/test/regress/resultmap postgresql-7.2b2.patched/src/test/regress/resultmap *** postgresql-7.2b2/src/test/regress/resultmap Sat Aug 25 19:55:15 2001 --- postgresql-7.2b2.patched/src/test/regress/resultmap Sun Nov 18 02:14:25 2001 *************** *** 3,13 **** --- 3,17 ---- abstime/sparc-sun-solaris=abstime-solaris-1947 abstime/.*-sco=abstime-solaris-1947 abstime/.*-sysv5=abstime-solaris-1947 + abstime/.*-nto=abstime-solaris-1947 + time/.*-nto=time float4/.*-qnx=float4-exp-three-digits + float4/.*-nto=float4 float8/.*-freebsd=float8-small-is-zero float8/i.86-.*-openbsd=float8-small-is-zero float8/i.86-.*-netbsd=float8-small-is-zero float8/.*-qnx=float8-exp-three-digits + float8/.*-nto=float8 float8/alpha.*-dec-osf.*:cc=float8-fp-exception float8/i.86-pc-cygwin=float8-small-is-zero geometry/.*-bsdi=geometry-bsdi-precision *************** *** 31,36 **** --- 35,41 ---- geometry/sparc.*-linux-gnu=geometry-solaris-precision geometry/alpha.*-linux-gnu=geometry-solaris-precision geometry/.*-beos=geometry-intel-beos + geometry/.*-nto=geometry-x86-pc-nto-qnx horology/.*-aix4=horology-no-DST-before-1970 horology/.*-irix6=horology-no-DST-before-1970 horology/alpha.*-dec-osf=horology-solaris-1947 *************** *** 40,48 **** --- 45,57 ---- horology/sparc-sun-solaris=horology-solaris-1947 horology/.*-sysv5=horology-solaris-1947 horology/.*-sco=horology-solaris-1947 + horology/.*-nto=horology-solaris-1947 int8/.*-qnx=int8-exp-three-digits + int8/.*-nto=int8 tinterval/alpha.*-dec-osf=tinterval-solaris-1947 tinterval/i.86-pc-solaris=tinterval-solaris-1947 tinterval/sparc-sun-solaris=tinterval-solaris-1947 tinterval/.*-sysv5=tinterval-solaris-1947 tinterval/.*-sco=tinterval-solaris-1947 + tinterval/.*-nto=tinterval-solaris-1947 + interval/.*-nto=interval