Pass shared memory address on command line to exec'ed backend.
authorBruce Momjian
Thu, 8 May 2003 14:49:04 +0000 (14:49 +0000)
committerBruce Momjian
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,