#include <signal.h>
#include <time.h>
+#ifdef HAVE_SHM_OPEN
+#include "sys/mman.h"
+#endif
+
#include "mb/pg_wchar.h"
#include "getaddrinfo.h"
#include "getopt_long.h"
/* defaults */
static int n_connections = 10;
static int n_buffers = 50;
+static char *dynamic_shared_memory_type = NULL;
/*
* Warning messages for authentication methods
free(path);
}
+/*
+ * Determine which dynamic shared memory implementation should be used on
+ * this platform. POSIX shared memory is preferable because the default
+ * allocation limits are much higher than the limits for System V on most
+ * systems that support both, but the fact that a platform has shm_open
+ * doesn't guarantee that that call will succeed when attempted. So, we
+ * attempt to reproduce what the postmaster will do when allocating a POSIX
+ * segment in dsm_impl.c; if it doesn't work, we assume it won't work for
+ * the postmaster either, and configure the cluster for System V shared
+ * memory instead.
+ */
+static char *
+choose_dsm_implementation(void)
+{
+#ifdef HAVE_SHM_OPEN
+ int ntries = 10;
+
+ while (ntries > 0)
+ {
+ uint32 handle;
+ char name[64];
+ int fd;
+
+ handle = random();
+ snprintf(name, 64, "/PostgreSQL.%u", handle);
+ if ((fd = shm_open(name, O_CREAT | O_RDWR | O_EXCL, 0600)) != -1)
+ {
+ close(fd);
+ shm_unlink(name);
+ return "posix";
+ }
+ if (errno != EEXIST)
+ break;
+ --ntries;
+ }
+#endif
+
+#ifdef WIN32
+ return "windows";
+#else
+ return "sysv";
+#endif
+}
+
/*
* Determine platform-specific config settings
*
SYSTEMQUOTE "\"%s\" --boot -x0 %s "
"-c max_connections=%d "
"-c shared_buffers=%d "
+ "-c dynamic_shared_memory_type=none "
"< \"%s\" > \"%s\" 2>&1" SYSTEMQUOTE,
backend_exec, boot_options,
n_connections, test_buffs,
printf("%dMB\n", (n_buffers * (BLCKSZ / 1024)) / 1024);
else
printf("%dkB\n", n_buffers * (BLCKSZ / 1024));
+
+ printf(_("selecting dynamic shared memory implementation ... "));
+ fflush(stdout);
+ dynamic_shared_memory_type = choose_dsm_implementation();
+ printf("%s\n", dynamic_shared_memory_type);
}
/*
conflines = replace_token(conflines, "#log_timezone = 'GMT'", repltok);
}
+ snprintf(repltok, sizeof(repltok), "dynamic_shared_memory_type = %s",
+ dynamic_shared_memory_type);
+ conflines = replace_token(conflines, "#dynamic_shared_memory_type = posix",
+ repltok);
+
snprintf(path, sizeof(path), "%s/postgresql.conf", pg_data);
writefile(path, conflines);