diff options
Diffstat (limited to 'src/backend/storage/ipc/shmem.c')
-rw-r--r-- | src/backend/storage/ipc/shmem.c | 81 |
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; } |