@ -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 */
@ -274,13 +277,6 @@ ShmemInitHash(const char *name, /* table string name for shmem index */
hash_get_shared_size ( infoP , hash_flags ) ,
& 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 ;
}