aboutsummaryrefslogtreecommitdiff
path: root/src/backend/storage/ipc/shmem.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/storage/ipc/shmem.c')
-rw-r--r--src/backend/storage/ipc/shmem.c81
1 files changed, 44 insertions, 37 deletions
diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c
index 78106d01d58..5e6f9550227 100644
--- a/src/backend/storage/ipc/shmem.c
+++ b/src/backend/storage/ipc/shmem.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/storage/ipc/shmem.c,v 1.103 2010/01/02 16:57:51 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/storage/ipc/shmem.c,v 1.104 2010/04/28 16:54:16 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -213,13 +213,13 @@ InitShmemIndex(void)
int hash_flags;
/*
+ * Create the shared memory shmem index.
+ *
* Since ShmemInitHash calls ShmemInitStruct, which expects the ShmemIndex
* hashtable to exist already, we have a bit of a circularity problem in
* initializing the ShmemIndex itself. The special "ShmemIndex" hash
* table name will tell ShmemInitStruct to fake it.
*/
-
- /* create the shared memory shmem index */
info.keysize = SHMEM_INDEX_KEYSIZE;
info.entrysize = sizeof(ShmemIndexEnt);
hash_flags = HASH_ELEM;
@@ -227,8 +227,6 @@ InitShmemIndex(void)
ShmemIndex = ShmemInitHash("ShmemIndex",
SHMEM_INDEX_SIZE, SHMEM_INDEX_SIZE,
&info, hash_flags);
- if (!ShmemIndex)
- elog(FATAL, "could not initialize Shmem Index");
}
/*
@@ -236,8 +234,9 @@ InitShmemIndex(void)
* shared memory hash table.
*
* We assume caller is doing some kind of synchronization
- * so that two people don't try to create/initialize the
- * table at once.
+ * so that two processes don't try to create/initialize the same
+ * table at once. (In practice, all creations are done in the postmaster
+ * process; child processes should always be attaching to existing tables.)
*
* max_size is the estimated maximum number of hashtable entries. This is
* not a hard limit, but the access efficiency will degrade if it is
@@ -247,6 +246,10 @@ InitShmemIndex(void)
* init_size is the number of hashtable entries to preallocate. For a table
* whose maximum size is certain, this should be equal to max_size; that
* ensures that no run-time out-of-shared-memory failures can occur.
+ *
+ * Note: before Postgres 9.0, this function returned NULL for some failure
+ * cases. Now, it always throws error instead, so callers need not check
+ * for NULL.
*/
HTAB *
ShmemInitHash(const char *name, /* table string name for shmem index */
@@ -275,13 +278,6 @@ ShmemInitHash(const char *name, /* table string name for shmem index */
&found);
/*
- * If fail, shmem index is corrupted. Let caller give the error message
- * since it has more information
- */
- if (location == NULL)
- return NULL;
-
- /*
* if it already exists, attach to it rather than allocate and initialize
* new space
*/
@@ -295,18 +291,20 @@ ShmemInitHash(const char *name, /* table string name for shmem index */
}
/*
- * ShmemInitStruct -- Create/attach to a structure in shared
- * memory.
+ * ShmemInitStruct -- Create/attach to a structure in shared memory.
*
- * This is called during initialization to find or allocate
+ * This is called during initialization to find or allocate
* a data structure in shared memory. If no other process
* has created the structure, this routine allocates space
* for it. If it exists already, a pointer to the existing
- * table is returned.
+ * structure is returned.
+ *
+ * Returns: pointer to the object. *foundPtr is set TRUE if the object was
+ * already in the shmem index (hence, already initialized).
*
- * Returns: real pointer to the object. FoundPtr is TRUE if
- * the object is already in the shmem index (hence, already
- * initialized).
+ * Note: before Postgres 9.0, this function returned NULL for some failure
+ * cases. Now, it always throws error instead, so callers need not check
+ * for NULL.
*/
void *
ShmemInitStruct(const char *name, Size size, bool *foundPtr)
@@ -320,7 +318,9 @@ ShmemInitStruct(const char *name, Size size, bool *foundPtr)
{
PGShmemHeader *shmemseghdr = ShmemSegHdr;
+ /* Must be trying to create/attach to ShmemIndex itself */
Assert(strcmp(name, "ShmemIndex") == 0);
+
if (IsUnderPostmaster)
{
/* Must be initializing a (non-standalone) backend */
@@ -340,6 +340,12 @@ ShmemInitStruct(const char *name, Size size, bool *foundPtr)
*/
Assert(shmemseghdr->index == NULL);
structPtr = ShmemAlloc(size);
+ if (structPtr == NULL)
+ ereport(ERROR,
+ (errcode(ERRCODE_OUT_OF_MEMORY),
+ errmsg("not enough shared memory for data structure"
+ " \"%s\" (%lu bytes requested)",
+ name, (unsigned long) size)));
shmemseghdr->index = structPtr;
*foundPtr = FALSE;
}
@@ -356,7 +362,8 @@ ShmemInitStruct(const char *name, Size size, bool *foundPtr)
LWLockRelease(ShmemIndexLock);
ereport(ERROR,
(errcode(ERRCODE_OUT_OF_MEMORY),
- errmsg("out of shared memory")));
+ errmsg("could not create ShmemIndex entry for data structure \"%s\"",
+ name)));
}
if (*foundPtr)
@@ -364,15 +371,17 @@ ShmemInitStruct(const char *name, Size size, bool *foundPtr)
/*
* Structure is in the shmem index so someone else has allocated it
* already. The size better be the same as the size we are trying to
- * initialize to or there is a name conflict (or worse).
+ * initialize to, or there is a name conflict (or worse).
*/
if (result->size != size)
{
LWLockRelease(ShmemIndexLock);
-
- elog(WARNING, "ShmemIndex entry size is wrong");
- /* let caller print its message too */
- return NULL;
+ ereport(ERROR,
+ (errmsg("ShmemIndex entry size is wrong for data structure"
+ " \"%s\": expected %lu, actual %lu",
+ name,
+ (unsigned long) size,
+ (unsigned long) result->size)));
}
structPtr = result->location;
}
@@ -380,26 +389,24 @@ ShmemInitStruct(const char *name, Size size, bool *foundPtr)
{
/* It isn't in the table yet. allocate and initialize it */
structPtr = ShmemAlloc(size);
- if (!structPtr)
+ if (structPtr == NULL)
{
- /* out of memory */
- Assert(ShmemIndex);
+ /* out of memory; remove the failed ShmemIndex entry */
hash_search(ShmemIndex, name, HASH_REMOVE, NULL);
LWLockRelease(ShmemIndexLock);
-
- ereport(WARNING,
+ ereport(ERROR,
(errcode(ERRCODE_OUT_OF_MEMORY),
- errmsg("could not allocate shared memory segment \"%s\"",
- name)));
- *foundPtr = FALSE;
- return NULL;
+ errmsg("not enough shared memory for data structure"
+ " \"%s\" (%lu bytes requested)",
+ name, (unsigned long) size)));
}
result->size = size;
result->location = structPtr;
}
- Assert(ShmemAddrIsValid(structPtr));
LWLockRelease(ShmemIndexLock);
+
+ Assert(ShmemAddrIsValid(structPtr));
return structPtr;
}