Pass shared memory address on command line to exec'ed backend.
authorBruce Momjian <bruce@momjian.us>
Thu, 8 May 2003 14:49:04 +0000 (14:49 +0000)
committerBruce Momjian <bruce@momjian.us>
Thu, 8 May 2003 14:49:04 +0000 (14:49 +0000)
Allow backends to attached to specified shared memory address.

src/backend/bootstrap/bootstrap.c
src/backend/port/sysv_shmem.c
src/backend/postmaster/postmaster.c
src/backend/tcop/postgres.c
src/include/storage/pg_shmem.h

index 215e165cf72becdf72c2b352329436279e9ef07a..54b541a0d6c60985ab36c51498d2d0e1291118f5 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.155 2003/05/06 23:34:55 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.156 2003/05/08 14:49:03 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -286,10 +286,13 @@ BootstrapMain(int argc, char *argv[])
                        case 'p':
                        {
                                /* indicates fork from postmaster */
-                               char *p;
 #ifdef EXEC_BACKEND
-                               sscanf(optarg, "%d,", &UsedShmemSegID);
+                               char *p;
+
+                               sscanf(optarg, "%d,%p,", &UsedShmemSegID, &UsedShmemSegAddr);
                                p = strchr(optarg, ',');
+                               if (p)
+                                       p = strchr(p+1, ',');
                                if (p)
                                        dbname = strdup(p+1);
 #else
index c98aff5231eb26e0a0531fe644593a367f2951b4..9454c3e92cc6981022c596e1439dbc6dc47b1aa1 100644 (file)
@@ -10,7 +10,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/port/sysv_shmem.c,v 1.8 2003/05/06 23:34:55 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/port/sysv_shmem.c,v 1.9 2003/05/08 14:49:03 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -39,9 +39,8 @@ typedef int IpcMemoryId;              /* shared memory ID returned by shmget(2) */
 #define IPCProtection  (0600)  /* access/modify by user only */
 
 
-#ifdef EXEC_BACKEND
 IpcMemoryKey UsedShmemSegID = 0;
-#endif
+void *UsedShmemSegAddr = NULL;
 
 static void *InternalIpcMemoryCreate(IpcMemoryKey memKey, uint32 size);
 static void IpcMemoryDetach(int status, Datum shmaddr);
@@ -282,7 +281,7 @@ PrivateMemoryDelete(int status, Datum memaddr)
  *
  * Create a shared memory segment of the given size and initialize its
  * standard header.  Also, register an on_shmem_exit callback to release
- * the storage.
+ * the storage.  For an exec'ed backend, it just attaches.
  *
  * Dead Postgres segments are recycled if found, but we do not fail upon
  * collision with non-Postgres shmem segments. The idea here is to detect and
@@ -302,11 +301,9 @@ PGSharedMemoryCreate(uint32 size, bool makePrivate, int port)
        /* Room for a header? */
        Assert(size > MAXALIGN(sizeof(PGShmemHeader)));
 
-#ifdef EXEC_BACKEND
-       if (UsedShmemSegID != 0)
+       if (ExecBackend && UsedShmemSegID != 0)
                NextShmemSegID = UsedShmemSegID;
        else
-#endif
                NextShmemSegID = port * 1000 + 1;
 
        for (;;NextShmemSegID++)
@@ -320,25 +317,39 @@ PGSharedMemoryCreate(uint32 size, bool makePrivate, int port)
                        break;
                }
 
-               /* Try to create new segment */
-               memAddress = InternalIpcMemoryCreate(NextShmemSegID, size);
-               if (memAddress)
-                       break;                          /* successful create and attach */
+               /* If attach to fixed address, only try once */
+               if (ExecBackend && UsedShmemSegAddr != NULL && NextShmemSegID != UsedShmemSegID)
+               {
+                       fprintf(stderr, "Unable to attach to memory at fixed address: shmget(key=%d, addr=%p) failed: %s\n",
+                               (int) UsedShmemSegID, UsedShmemSegAddr, strerror(errno));
+                       proc_exit(1);
+               }
+
+               if (!ExecBackend || UsedShmemSegAddr == NULL)
+               {
+                       /* Try to create new segment */
+                       memAddress = InternalIpcMemoryCreate(NextShmemSegID, size);
+                       if (memAddress)
+                               break;                          /* successful create and attach */
+               }
 
                /* See if it looks to be leftover from a dead Postgres process */
                shmid = shmget(NextShmemSegID, sizeof(PGShmemHeader), 0);
                if (shmid < 0)
                        continue;                       /* failed: must be some other app's */
 
-#if defined(solaris) && defined(__sparc__)
                /* use intimate shared memory on SPARC Solaris */
-               memAddress = shmat(shmid, 0, SHM_SHARE_MMU);
+               memAddress = shmat(shmid, UsedShmemSegAddr,
+#if defined(solaris) && defined(__sparc__)
+                               SHM_SHARE_MMU
 #else
-               memAddress = shmat(shmid, 0, 0);
+                               0
 #endif
+                       );
 
                if (memAddress == (void *) -1)
                        continue;                       /* failed: must be some other app's */
+
                hdr = (PGShmemHeader *) memAddress;
                if (hdr->magic != PGShmemMagic)
                {
@@ -346,14 +357,19 @@ PGSharedMemoryCreate(uint32 size, bool makePrivate, int port)
                        continue;                       /* segment belongs to a non-Postgres app */
                }
 
+               /* Successfully attached to shared memory, which is all we wanted */
+               if (ExecBackend && UsedShmemSegAddr != NULL)
+                       break;
+
+               /* Check shared memory and possibly remove and recreate */
+                       
                /*
-                * If the creator PID is my own PID or does not belong to any
-                * extant process, it's safe to zap it.
+                * If I am not the creator and it belongs to an extant process,
+                * continue.
                 */
                if (hdr->creatorPID != getpid())
                {
-                       if (kill(hdr->creatorPID, 0) == 0 ||
-                               errno != ESRCH)
+                       if (kill(hdr->creatorPID, 0) == 0 || errno != ESRCH)
                        {
                                shmdt(memAddress);
                                continue;               /* segment belongs to a live process */
@@ -385,26 +401,31 @@ PGSharedMemoryCreate(uint32 size, bool makePrivate, int port)
                 */
        }
 
-       /*
-        * 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));
+       if (!ExecBackend || makePrivate || UsedShmemSegAddr == NULL)
+       {
+               /*
+                * 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->creatorPID = getpid();
+               hdr->magic = PGShmemMagic;
+       
+               /*
+                * Initialize space allocation status for segment.
+                */
+               hdr->totalsize = size;
+               hdr->freeoffset = MAXALIGN(sizeof(PGShmemHeader));
+       }
 
-#ifdef EXEC_BACKEND
-       if (!makePrivate && UsedShmemSegID == 0)
+       if (ExecBackend && !makePrivate && UsedShmemSegAddr == NULL)
+       {
+               UsedShmemSegAddr = memAddress;
                UsedShmemSegID = NextShmemSegID;
-#endif
+       }
 
        return hdr;
 }
index 23c948ce2ba237feed6d67c571216cc35cee284f..211fc216f9cb9b35916e9995b13f8a90c72bffc6 100644 (file)
@@ -37,7 +37,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.322 2003/05/06 23:34:55 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.323 2003/05/08 14:49:03 momjian Exp $
  *
  * NOTES
  *
@@ -2439,9 +2439,10 @@ BackendFinalize(Port *port)
         */
        av[ac++] = "-p";
 #ifdef EXEC_BACKEND
-       Assert(UsedShmemSegID != 0);
+       Assert(UsedShmemSegID != 0 && UsedShmemSegAddr != NULL);
        /* database name at the end because it might contain commas */
-       snprintf(pbuf, NAMEDATALEN + 256, "%d,%d,%s", port->sock, UsedShmemSegID, port->database_name);
+       snprintf(pbuf, NAMEDATALEN + 256, "%d,%d,%p,%s", port->sock,
+                                       UsedShmemSegID, UsedShmemSegAddr, port->database_name);
        av[ac++] = pbuf;
 #else
        av[ac++] = port->database_name;
@@ -2776,9 +2777,10 @@ SSDataBase(int xlop)
 
                av[ac++] = "-p";
 #ifdef EXEC_BACKEND
-               Assert(UsedShmemSegID != 0);
+               Assert(UsedShmemSegID != 0 && UsedShmemSegAddr != NULL);
                /* database name at the end because it might contain commas */
-               snprintf(pbuf, NAMEDATALEN + 256, "%d,%s", UsedShmemSegID, "template1");
+               snprintf(pbuf, NAMEDATALEN + 256, "%d,%p,%s", UsedShmemSegID,
+                                               UsedShmemSegAddr, "template1");
                av[ac++] = pbuf;
 #else
                av[ac++] = "template1";
index 78696cd0771b82d87903dae270dad5e3cb846049..895645587085cfb2d31c45bc5bc1f4df44911395 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.338 2003/05/06 23:34:55 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.339 2003/05/08 14:49:04 momjian Exp $
  *
  * NOTES
  *       this is the "main" module of the postgres backend and
@@ -2025,13 +2025,17 @@ PostgresMain(int argc, char *argv[], const char *username)
                                 */
                                if (secure)
                                {
-                                       char *p;
 #ifdef EXEC_BACKEND
-                                       sscanf(optarg, "%d,%d,", &MyProcPort->sock, &UsedShmemSegID);
+                                       char *p;
+
+                                       sscanf(optarg, "%d,%d,%p,", &MyProcPort->sock,
+                                                                       &UsedShmemSegID, &UsedShmemSegAddr);
                                        /* Grab dbname as last param */
                                        p = strchr(optarg, ',');
                                        if (p)
                                                p = strchr(p+1, ',');
+                                       if (p)                                  
+                                               p = strchr(p+1, ',');
                                        if (p)                                  
                                                dbname = strdup(p+1);
 #else
@@ -2393,7 +2397,7 @@ PostgresMain(int argc, char *argv[], const char *username)
        if (!IsUnderPostmaster)
        {
                puts("\nPOSTGRES backend interactive interface ");
-               puts("$Revision: 1.338 $ $Date: 2003/05/06 23:34:55 $\n");
+               puts("$Revision: 1.339 $ $Date: 2003/05/08 14:49:04 $\n");
        }
 
        /*
index 5f9df7602a1082bcf8e7c3fef0c06f1deabd4fbe..0c2b9cb299d56c896e4eacea1779bdf748aeed44 100644 (file)
@@ -17,7 +17,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_shmem.h,v 1.5 2003/05/06 23:34:56 momjian Exp $
+ * $Id: pg_shmem.h,v 1.6 2003/05/08 14:49:04 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -38,6 +38,7 @@ typedef struct PGShmemHeader  /* standard header for all Postgres shmem */
 
 #ifdef EXEC_BACKEND
 extern IpcMemoryKey UsedShmemSegID;
+extern void *UsedShmemSegAddr;
 #endif
 
 extern PGShmemHeader *PGSharedMemoryCreate(uint32 size, bool makePrivate,