@ -50,6 +50,7 @@
# include "postmaster/autovacuum.h"
# include "postmaster/fork_process.h"
# include "postmaster/postmaster.h"
# include "replication/walsender.h"
# include "storage/backendid.h"
# include "storage/dsm.h"
# include "storage/fd.h"
@ -102,6 +103,18 @@
# define PGSTAT_FUNCTION_HASH_SIZE 512
/* ----------
* Total number of backends including auxiliary
*
* We reserve a slot for each possible BackendId , plus one for each
* possible auxiliary process type . ( This scheme assumes there is not
* more than one of any auxiliary process type at a time . ) MaxBackends
* includes autovacuum workers and background workers as well .
* - - - - - - - - - -
*/
# define NumBackendStatSlots (MaxBackends + NUM_AUXPROCTYPES)
/* ----------
* GUC parameters
* - - - - - - - - - -
@ -212,7 +225,11 @@ typedef struct TwoPhasePgStatRecord
*/
static MemoryContext pgStatLocalContext = NULL ;
static HTAB * pgStatDBHash = NULL ;
/* Status for backends including auxiliary */
static LocalPgBackendStatus * localBackendStatusTable = NULL ;
/* Total number of backends including auxiliary */
static int localNumBackends = 0 ;
/*
@ -2505,20 +2522,20 @@ BackendStatusShmemSize(void)
Size size ;
/* BackendStatusArray: */
size = mul_size ( sizeof ( PgBackendStatus ) , MaxBackend s) ;
size = mul_size ( sizeof ( PgBackendStatus ) , NumBackendStatSlot s) ;
/* BackendAppnameBuffer: */
size = add_size ( size ,
mul_size ( NAMEDATALEN , MaxBackend s) ) ;
mul_size ( NAMEDATALEN , NumBackendStatSlot s) ) ;
/* BackendClientHostnameBuffer: */
size = add_size ( size ,
mul_size ( NAMEDATALEN , MaxBackend s) ) ;
mul_size ( NAMEDATALEN , NumBackendStatSlot s) ) ;
/* BackendActivityBuffer: */
size = add_size ( size ,
mul_size ( pgstat_track_activity_query_size , MaxBackend s) ) ;
mul_size ( pgstat_track_activity_query_size , NumBackendStatSlot s) ) ;
# ifdef USE_SSL
/* BackendSslStatusBuffer: */
size = add_size ( size ,
mul_size ( sizeof ( PgBackendSSLStatus ) , MaxBackend s) ) ;
mul_size ( sizeof ( PgBackendSSLStatus ) , NumBackendStatSlot s) ) ;
# endif
return size ;
}
@ -2536,7 +2553,7 @@ CreateSharedBackendStatus(void)
char * buffer ;
/* Create or attach to the shared array */
size = mul_size ( sizeof ( PgBackendStatus ) , MaxBackend s) ;
size = mul_size ( sizeof ( PgBackendStatus ) , NumBackendStatSlot s) ;
BackendStatusArray = ( PgBackendStatus * )
ShmemInitStruct ( " Backend Status Array " , size , & found ) ;
@ -2559,7 +2576,7 @@ CreateSharedBackendStatus(void)
/* Initialize st_appname pointers. */
buffer = BackendAppnameBuffer ;
for ( i = 0 ; i < MaxBackend s; i + + )
for ( i = 0 ; i < NumBackendStatSlot s; i + + )
{
BackendStatusArray [ i ] . st_appname = buffer ;
buffer + = NAMEDATALEN ;
@ -2577,7 +2594,7 @@ CreateSharedBackendStatus(void)
/* Initialize st_clienthostname pointers. */
buffer = BackendClientHostnameBuffer ;
for ( i = 0 ; i < MaxBackend s; i + + )
for ( i = 0 ; i < NumBackendStatSlot s; i + + )
{
BackendStatusArray [ i ] . st_clienthostname = buffer ;
buffer + = NAMEDATALEN ;
@ -2586,7 +2603,7 @@ CreateSharedBackendStatus(void)
/* Create or attach to the shared activity buffer */
BackendActivityBufferSize = mul_size ( pgstat_track_activity_query_size ,
MaxBackend s) ;
NumBackendStatSlot s) ;
BackendActivityBuffer = ( char * )
ShmemInitStruct ( " Backend Activity Buffer " ,
BackendActivityBufferSize ,
@ -2598,7 +2615,7 @@ CreateSharedBackendStatus(void)
/* Initialize st_activity pointers. */
buffer = BackendActivityBuffer ;
for ( i = 0 ; i < MaxBackend s; i + + )
for ( i = 0 ; i < NumBackendStatSlot s; i + + )
{
BackendStatusArray [ i ] . st_activity = buffer ;
buffer + = pgstat_track_activity_query_size ;
@ -2607,7 +2624,7 @@ CreateSharedBackendStatus(void)
# ifdef USE_SSL
/* Create or attach to the shared SSL status buffer */
size = mul_size ( sizeof ( PgBackendSSLStatus ) , MaxBackend s) ;
size = mul_size ( sizeof ( PgBackendSSLStatus ) , NumBackendStatSlot s) ;
BackendSslStatusBuffer = ( PgBackendSSLStatus * )
ShmemInitStruct ( " Backend SSL Status Buffer " , size , & found ) ;
@ -2619,7 +2636,7 @@ CreateSharedBackendStatus(void)
/* Initialize st_sslstatus pointers. */
ptr = BackendSslStatusBuffer ;
for ( i = 0 ; i < MaxBackend s; i + + )
for ( i = 0 ; i < NumBackendStatSlot s; i + + )
{
BackendStatusArray [ i ] . st_sslstatus = ptr ;
ptr + + ;
@ -2633,7 +2650,8 @@ CreateSharedBackendStatus(void)
* pgstat_initialize ( ) -
*
* Initialize pgstats state , and set up our on - proc - exit hook .
* Called from InitPostgres . MyBackendId must be set ,
* Called from InitPostgres and AuxiliaryProcessMain . For auxiliary process ,
* MyBackendId is invalid . Otherwise , MyBackendId must be set ,
* but we must not have started any transaction yet ( since the
* exit hook must run after the last transaction exit ) .
* NOTE : MyDatabaseId isn ' t set yet ; so the shutdown hook has to be careful .
@ -2643,8 +2661,26 @@ void
pgstat_initialize ( void )
{
/* Initialize MyBEEntry */
Assert ( MyBackendId > = 1 & & MyBackendId < = MaxBackends ) ;
MyBEEntry = & BackendStatusArray [ MyBackendId - 1 ] ;
if ( MyBackendId ! = InvalidBackendId )
{
Assert ( MyBackendId > = 1 & & MyBackendId < = MaxBackends ) ;
MyBEEntry = & BackendStatusArray [ MyBackendId - 1 ] ;
}
else
{
/* Must be an auxiliary process */
Assert ( MyAuxProcType ! = NotAnAuxProcess ) ;
/*
* Assign the MyBEEntry for an auxiliary process . Since it doesn ' t
* have a BackendId , the slot is statically allocated based on the
* auxiliary process type ( MyAuxProcType ) . Backends use slots indexed
* in the range from 1 to MaxBackends ( inclusive ) , so we use
* MaxBackends + AuxBackendType + 1 as the index of the slot for an
* auxiliary process .
*/
MyBEEntry = & BackendStatusArray [ MaxBackends + MyAuxProcType ] ;
}
/* Set up a process-exit hook to clean up */
on_shmem_exit ( pgstat_beshutdown_hook , 0 ) ;
@ -2655,15 +2691,16 @@ pgstat_initialize(void)
*
* Initialize this backend ' s entry in the PgBackendStatus array .
* Called from InitPostgres .
* MyDatabaseId , session userid , and application_name must be set
* ( hence , this cannot be combined with pgstat_initialize ) .
*
* Apart from auxiliary processes , MyBackendId , MyDatabaseId ,
* session userid , and application_name must be set for a
* backend ( hence , this cannot be combined with pgstat_initialize ) .
* - - - - - - - - - -
*/
void
pgstat_bestart ( void )
{
TimestampTz proc_start_timestamp ;
Oid userid ;
SockAddr clientaddr ;
volatile PgBackendStatus * beentry ;
@ -2678,7 +2715,6 @@ pgstat_bestart(void)
proc_start_timestamp = MyProcPort - > SessionStartTime ;
else
proc_start_timestamp = GetCurrentTimestamp ( ) ;
userid = GetSessionUserId ( ) ;
/*
* We may not have a MyProcPort ( eg , if this is the autovacuum process ) .
@ -2697,6 +2733,66 @@ pgstat_bestart(void)
* cute .
*/
beentry = MyBEEntry ;
/* pgstats state must be initialized from pgstat_initialize() */
Assert ( beentry ! = NULL ) ;
if ( MyBackendId ! = InvalidBackendId )
{
if ( IsAutoVacuumLauncherProcess ( ) )
{
/* Autovacuum Launcher */
beentry - > st_backendType = B_AUTOVAC_LAUNCHER ;
}
else if ( IsAutoVacuumWorkerProcess ( ) )
{
/* Autovacuum Worker */
beentry - > st_backendType = B_AUTOVAC_WORKER ;
}
else if ( am_walsender )
{
/* Wal sender */
beentry - > st_backendType = B_WAL_SENDER ;
}
else if ( IsBackgroundWorker )
{
/* bgworker */
beentry - > st_backendType = B_BG_WORKER ;
}
else
{
/* client-backend */
beentry - > st_backendType = B_BACKEND ;
}
}
else
{
/* Must be an auxiliary process */
Assert ( MyAuxProcType ! = NotAnAuxProcess ) ;
switch ( MyAuxProcType )
{
case StartupProcess :
beentry - > st_backendType = B_STARTUP ;
break ;
case BgWriterProcess :
beentry - > st_backendType = B_BG_WRITER ;
break ;
case CheckpointerProcess :
beentry - > st_backendType = B_CHECKPOINTER ;
break ;
case WalWriterProcess :
beentry - > st_backendType = B_WAL_WRITER ;
break ;
case WalReceiverProcess :
beentry - > st_backendType = B_WAL_RECEIVER ;
break ;
default :
elog ( FATAL , " unrecognized process type: %d " ,
( int ) MyAuxProcType ) ;
proc_exit ( 1 ) ;
}
}
do
{
pgstat_increment_changecount_before ( beentry ) ;
@ -2708,7 +2804,15 @@ pgstat_bestart(void)
beentry - > st_state_start_timestamp = 0 ;
beentry - > st_xact_start_timestamp = 0 ;
beentry - > st_databaseid = MyDatabaseId ;
beentry - > st_userid = userid ;
/* We have userid for client-backends, wal-sender and bgworker processes */
if ( beentry - > st_backendType = = B_BACKEND
| | beentry - > st_backendType = = B_WAL_SENDER
| | beentry - > st_backendType = = B_BG_WORKER )
beentry - > st_userid = GetSessionUserId ( ) ;
else
beentry - > st_userid = InvalidOid ;
beentry - > st_clientaddr = clientaddr ;
if ( MyProcPort & & MyProcPort - > remote_hostname )
strlcpy ( beentry - > st_clienthostname , MyProcPort - > remote_hostname ,
@ -3046,24 +3150,24 @@ pgstat_read_current_status(void)
localtable = ( LocalPgBackendStatus * )
MemoryContextAlloc ( pgStatLocalContext ,
sizeof ( LocalPgBackendStatus ) * MaxBackend s) ;
sizeof ( LocalPgBackendStatus ) * NumBackendStatSlot s) ;
localappname = ( char * )
MemoryContextAlloc ( pgStatLocalContext ,
NAMEDATALEN * MaxBackend s) ;
NAMEDATALEN * NumBackendStatSlot s) ;
localactivity = ( char * )
MemoryContextAlloc ( pgStatLocalContext ,
pgstat_track_activity_query_size * MaxBackend s) ;
pgstat_track_activity_query_size * NumBackendStatSlot s) ;
# ifdef USE_SSL
localsslstatus = ( PgBackendSSLStatus * )
MemoryContextAlloc ( pgStatLocalContext ,
sizeof ( PgBackendSSLStatus ) * MaxBackend s) ;
sizeof ( PgBackendSSLStatus ) * NumBackendStatSlot s) ;
# endif
localNumBackends = 0 ;
beentry = BackendStatusArray ;
localentry = localtable ;
for ( i = 1 ; i < = MaxBackend s; i + + )
for ( i = 1 ; i < = NumBackendStatSlot s; i + + )
{
/*
* Follow the protocol of retrying if st_changecount changes while we
@ -3829,7 +3933,47 @@ pgstat_get_crashed_backend_activity(int pid, char *buffer, int buflen)
return NULL ;
}
const char *
pgstat_get_backend_desc ( BackendType backendType )
{
const char * backendDesc = " unknown process type " ;
switch ( backendType )
{
case B_AUTOVAC_LAUNCHER :
backendDesc = " autovacuum launcher " ;
break ;
case B_AUTOVAC_WORKER :
backendDesc = " autovacuum worker " ;
break ;
case B_BACKEND :
backendDesc = " client backend " ;
break ;
case B_BG_WORKER :
backendDesc = " background worker " ;
break ;
case B_BG_WRITER :
backendDesc = " background writer " ;
break ;
case B_CHECKPOINTER :
backendDesc = " checkpointer " ;
break ;
case B_STARTUP :
backendDesc = " startup " ;
break ;
case B_WAL_RECEIVER :
backendDesc = " walreceiver " ;
break ;
case B_WAL_SENDER :
backendDesc = " walsender " ;
break ;
case B_WAL_WRITER :
backendDesc = " walwriter " ;
break ;
}
return backendDesc ;
}
/* ------------------------------------------------------------
* Local support functions follow
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -