Обсуждение: Re: Re: [PATCHES] PostgreSQL virtual hosting support
Re: Re: [PATCHES] PostgreSQL virtual hosting support
От
djm@web.us.uu.net (David J. MacKenzie)
Дата:
> I was afraid you were planning to run that way. Did you absorb the > point about shared memory keys being based (only) on the port number? > Unless something's done about that, the above configuration will NOT > work, because the different instances will try to use the same > shared memory and semaphore sets. Yes, my patch addresses that issue, as well as I could figure out to do. Here's part of the code I submitted in postmaster.c: /* + * get_host_port -- return a pseudo port number (16 bits) + * derived from the primary IP address of HostName. + */ + static unsigned short + get_host_port(void) + { + static unsigned short hostPort = 0; + + if (hostPort == 0) + { + SockAddr saddr; + struct hostent *hp; + + hp = gethostbyname(HostName); + if ((hp == NULL) || (hp->h_addrtype != AF_INET)) + { + char msg[1024]; + snprintf(msg, sizeof(msg), + "FATAL: get_host_port: gethostbyname(%s) failed: %s\n", + HostName, hstrerror(h_errno)); + fputs(msg, stderr); + pqdebug("%s", msg); + exit(1); + } + memmove((char *) &(saddr.in.sin_addr), + (char *) hp->h_addr, + hp->h_length); + hostPort = ntohl(saddr.in.sin_addr.s_addr) & 0xFFFF; + } + + return hostPort; + } + + /* * reset_shared -- reset shared memory and semaphores */ static void reset_shared(unsigned short port) { + /* + * A typical ipc_key is 5432001, which is port 5432, sequence + * number 0, and 01 as the index in IPCKeyGetBufferMemoryKey(). + * The 32-bit INT_MAX is 2147483 6 47. + * + * The default algorithm for calculating the IPC keys assumes that all + * instances of postmaster on a given host are listening on different + * ports. In order to work (prevent shared memory collisions) if you + * run multiple PostgreSQL instances on the same port and different IP + * addresses on a host, we change the algorithm if you give postmaster + * the -h option, or set PGHOST, to a value other than the internal + * default of "any". + * + * If HostName is not "any", then we generate the IPC keys using the + * last two octets of the IP address instead of the port number. + * This algorithm assumes that no one will run multiple PostgreSQL + * instances on one host using two IP addresses that have the same two + * last octets in different class C networks. If anyone does, it + * would be rare. + * + * So, if you use -h or PGHOST, don't try to run two instances of + * PostgreSQL on the same IP address but different ports. If you + * don't use them, then you must use different ports (via -p or + * PGPORT). And, of course, don't try to use both approaches on one + * host. + */ + + if (strcmp(HostName, "any")) + port = get_host_port(); + ipc_key = port * 1000 + shmem_seq * 100; CreateSharedMemoryAndSemaphores(ipc_key, MaxBackends);