]> granicus.if.org Git - postgresql/commitdiff
initdb: Select working dynamic shared memory implementation.
authorRobert Haas <rhaas@postgresql.org>
Thu, 10 Oct 2013 23:38:56 +0000 (19:38 -0400)
committerRobert Haas <rhaas@postgresql.org>
Thu, 10 Oct 2013 23:46:31 +0000 (19:46 -0400)
If POSIX shared memory is supported and works, we prefer it.
Otherwise, we prefer System V, except on Windows, where we use
the implementation specific to that platform.

src/bin/initdb/initdb.c

index a6eb0d806162b0665acd1b58ca440bfa6d35c0c0..ebe8a67c0b548f89d7a0abda2e4b2f56112610ce 100644 (file)
 #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"
@@ -150,6 +154,7 @@ static char *pgdata_native;
 /* defaults */
 static int     n_connections = 10;
 static int     n_buffers = 50;
+static char *dynamic_shared_memory_type = NULL;
 
 /*
  * Warning messages for authentication methods
@@ -1076,6 +1081,50 @@ set_null_conf(void)
        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
  *
@@ -1157,6 +1206,7 @@ test_config_settings(void)
                                 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,
@@ -1171,6 +1221,11 @@ test_config_settings(void)
                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);
 }
 
 /*
@@ -1265,6 +1320,11 @@ setup_config(void)
                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);