LCOV - differential code coverage report
Current view: top level - src/backend/utils/activity - backend_status.c (source / functions) Coverage Total Hit UNC UBC GBC GNC CBC DCB
Current: Differential Code Coverage 16@8cea358b128 vs 17@8cea358b128 Lines: 93.0 % 341 317 24 2 11 304 13
Current Date: 2024-04-14 14:21:10 Functions: 100.0 % 21 21 5 16 2
Baseline: 16@8cea358b128 Branches: 63.3 % 256 162 3 91 3 5 154
Baseline Date: 2024-04-14 14:21:09 Line coverage date bins:
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed [..60] days: 100.0 % 11 11 11
(180,240] days: 88.9 % 9 8 1 8
(240..) days: 92.8 % 321 298 23 2 296
Function coverage date bins:
[..60] days: 100.0 % 2 2 2
(180,240] days: 100.0 % 1 1 1
(240..) days: 100.0 % 18 18 3 15
Branch coverage date bins:
[..60] days: 62.5 % 8 5 3 5
(180,240] days: 50.0 % 6 3 3 3
(240..) days: 63.6 % 242 154 88 3 151

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /* ----------
                                  2                 :                :  * backend_status.c
                                  3                 :                :  *    Backend status reporting infrastructure.
                                  4                 :                :  *
                                  5                 :                :  * Copyright (c) 2001-2024, PostgreSQL Global Development Group
                                  6                 :                :  *
                                  7                 :                :  *
                                  8                 :                :  * IDENTIFICATION
                                  9                 :                :  *    src/backend/utils/activity/backend_status.c
                                 10                 :                :  * ----------
                                 11                 :                :  */
                                 12                 :                : #include "postgres.h"
                                 13                 :                : 
                                 14                 :                : #include "access/xact.h"
                                 15                 :                : #include "libpq/libpq-be.h"
                                 16                 :                : #include "miscadmin.h"
                                 17                 :                : #include "pg_trace.h"
                                 18                 :                : #include "pgstat.h"
                                 19                 :                : #include "port/atomics.h"     /* for memory barriers */
                                 20                 :                : #include "storage/ipc.h"
                                 21                 :                : #include "storage/proc.h"     /* for MyProc */
                                 22                 :                : #include "storage/procarray.h"
                                 23                 :                : #include "storage/sinvaladt.h"
                                 24                 :                : #include "utils/ascii.h"
                                 25                 :                : #include "utils/guc.h"            /* for application_name */
                                 26                 :                : #include "utils/memutils.h"
                                 27                 :                : 
                                 28                 :                : 
                                 29                 :                : /* ----------
                                 30                 :                :  * Total number of backends including auxiliary
                                 31                 :                :  *
                                 32                 :                :  * We reserve a slot for each possible PGPROC entry, including aux processes.
                                 33                 :                :  * (But not including PGPROC entries reserved for prepared xacts; they are not
                                 34                 :                :  * real processes.)
                                 35                 :                :  * ----------
                                 36                 :                :  */
                                 37                 :                : #define NumBackendStatSlots (MaxBackends + NUM_AUXILIARY_PROCS)
                                 38                 :                : 
                                 39                 :                : 
                                 40                 :                : /* ----------
                                 41                 :                :  * GUC parameters
                                 42                 :                :  * ----------
                                 43                 :                :  */
                                 44                 :                : bool        pgstat_track_activities = false;
                                 45                 :                : int         pgstat_track_activity_query_size = 1024;
                                 46                 :                : 
                                 47                 :                : 
                                 48                 :                : /* exposed so that backend_progress.c can access it */
                                 49                 :                : PgBackendStatus *MyBEEntry = NULL;
                                 50                 :                : 
                                 51                 :                : 
                                 52                 :                : static PgBackendStatus *BackendStatusArray = NULL;
                                 53                 :                : static char *BackendAppnameBuffer = NULL;
                                 54                 :                : static char *BackendClientHostnameBuffer = NULL;
                                 55                 :                : static char *BackendActivityBuffer = NULL;
                                 56                 :                : static Size BackendActivityBufferSize = 0;
                                 57                 :                : #ifdef USE_SSL
                                 58                 :                : static PgBackendSSLStatus *BackendSslStatusBuffer = NULL;
                                 59                 :                : #endif
                                 60                 :                : #ifdef ENABLE_GSS
                                 61                 :                : static PgBackendGSSStatus *BackendGssStatusBuffer = NULL;
                                 62                 :                : #endif
                                 63                 :                : 
                                 64                 :                : 
                                 65                 :                : /* Status for backends including auxiliary */
                                 66                 :                : static LocalPgBackendStatus *localBackendStatusTable = NULL;
                                 67                 :                : 
                                 68                 :                : /* Total number of backends including auxiliary */
                                 69                 :                : static int  localNumBackends = 0;
                                 70                 :                : 
                                 71                 :                : static MemoryContext backendStatusSnapContext;
                                 72                 :                : 
                                 73                 :                : 
                                 74                 :                : static void pgstat_beshutdown_hook(int code, Datum arg);
                                 75                 :                : static void pgstat_read_current_status(void);
                                 76                 :                : static void pgstat_setup_backend_status_context(void);
                                 77                 :                : 
                                 78                 :                : 
                                 79                 :                : /*
                                 80                 :                :  * Report shared-memory space needed by CreateSharedBackendStatus.
                                 81                 :                :  */
                                 82                 :                : Size
 1107 andres@anarazel.de         83                 :CBC        1679 : BackendStatusShmemSize(void)
                                 84                 :                : {
                                 85                 :                :     Size        size;
                                 86                 :                : 
                                 87                 :                :     /* BackendStatusArray: */
  733 rhaas@postgresql.org       88                 :           1679 :     size = mul_size(sizeof(PgBackendStatus), NumBackendStatSlots);
                                 89                 :                :     /* BackendAppnameBuffer: */
 1107 andres@anarazel.de         90                 :           1679 :     size = add_size(size,
  733 rhaas@postgresql.org       91                 :           1679 :                     mul_size(NAMEDATALEN, NumBackendStatSlots));
                                 92                 :                :     /* BackendClientHostnameBuffer: */
 1107 andres@anarazel.de         93                 :           1679 :     size = add_size(size,
  733 rhaas@postgresql.org       94                 :           1679 :                     mul_size(NAMEDATALEN, NumBackendStatSlots));
                                 95                 :                :     /* BackendActivityBuffer: */
 1107 andres@anarazel.de         96                 :           1679 :     size = add_size(size,
  733 rhaas@postgresql.org       97                 :           1679 :                     mul_size(pgstat_track_activity_query_size, NumBackendStatSlots));
                                 98                 :                : #ifdef USE_SSL
                                 99                 :                :     /* BackendSslStatusBuffer: */
 1107 andres@anarazel.de        100                 :           1679 :     size = add_size(size,
  733 rhaas@postgresql.org      101                 :           1679 :                     mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots));
                                102                 :                : #endif
                                103                 :                : #ifdef ENABLE_GSS
                                104                 :                :     /* BackendGssStatusBuffer: */
 1107 andres@anarazel.de        105                 :           1679 :     size = add_size(size,
  733 rhaas@postgresql.org      106                 :           1679 :                     mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots));
                                107                 :                : #endif
 1107 andres@anarazel.de        108                 :           1679 :     return size;
                                109                 :                : }
                                110                 :                : 
                                111                 :                : /*
                                112                 :                :  * Initialize the shared status array and several string buffers
                                113                 :                :  * during postmaster startup.
                                114                 :                :  */
                                115                 :                : void
                                116                 :            898 : CreateSharedBackendStatus(void)
                                117                 :                : {
                                118                 :                :     Size        size;
                                119                 :                :     bool        found;
                                120                 :                :     int         i;
                                121                 :                :     char       *buffer;
                                122                 :                : 
                                123                 :                :     /* Create or attach to the shared array */
  733 rhaas@postgresql.org      124                 :            898 :     size = mul_size(sizeof(PgBackendStatus), NumBackendStatSlots);
 1107 andres@anarazel.de        125                 :            898 :     BackendStatusArray = (PgBackendStatus *)
                                126                 :            898 :         ShmemInitStruct("Backend Status Array", size, &found);
                                127                 :                : 
                                128         [ +  - ]:            898 :     if (!found)
                                129                 :                :     {
                                130                 :                :         /*
                                131                 :                :          * We're the first - initialize.
                                132                 :                :          */
                                133   [ +  -  +  -  :            898 :         MemSet(BackendStatusArray, 0, size);
                                     +  -  -  +  -  
                                                 - ]
                                134                 :                :     }
                                135                 :                : 
                                136                 :                :     /* Create or attach to the shared appname buffer */
  733 rhaas@postgresql.org      137                 :            898 :     size = mul_size(NAMEDATALEN, NumBackendStatSlots);
 1107 andres@anarazel.de        138                 :            898 :     BackendAppnameBuffer = (char *)
                                139                 :            898 :         ShmemInitStruct("Backend Application Name Buffer", size, &found);
                                140                 :                : 
                                141         [ +  - ]:            898 :     if (!found)
                                142                 :                :     {
                                143   [ +  -  +  -  :            898 :         MemSet(BackendAppnameBuffer, 0, size);
                                     +  -  -  +  -  
                                                 - ]
                                144                 :                : 
                                145                 :                :         /* Initialize st_appname pointers. */
                                146                 :            898 :         buffer = BackendAppnameBuffer;
  733 rhaas@postgresql.org      147         [ +  + ]:          80720 :         for (i = 0; i < NumBackendStatSlots; i++)
                                148                 :                :         {
 1107 andres@anarazel.de        149                 :          79822 :             BackendStatusArray[i].st_appname = buffer;
                                150                 :          79822 :             buffer += NAMEDATALEN;
                                151                 :                :         }
                                152                 :                :     }
                                153                 :                : 
                                154                 :                :     /* Create or attach to the shared client hostname buffer */
  733 rhaas@postgresql.org      155                 :            898 :     size = mul_size(NAMEDATALEN, NumBackendStatSlots);
 1107 andres@anarazel.de        156                 :            898 :     BackendClientHostnameBuffer = (char *)
                                157                 :            898 :         ShmemInitStruct("Backend Client Host Name Buffer", size, &found);
                                158                 :                : 
                                159         [ +  - ]:            898 :     if (!found)
                                160                 :                :     {
                                161   [ +  -  +  -  :            898 :         MemSet(BackendClientHostnameBuffer, 0, size);
                                     +  -  -  +  -  
                                                 - ]
                                162                 :                : 
                                163                 :                :         /* Initialize st_clienthostname pointers. */
                                164                 :            898 :         buffer = BackendClientHostnameBuffer;
  733 rhaas@postgresql.org      165         [ +  + ]:          80720 :         for (i = 0; i < NumBackendStatSlots; i++)
                                166                 :                :         {
 1107 andres@anarazel.de        167                 :          79822 :             BackendStatusArray[i].st_clienthostname = buffer;
                                168                 :          79822 :             buffer += NAMEDATALEN;
                                169                 :                :         }
                                170                 :                :     }
                                171                 :                : 
                                172                 :                :     /* Create or attach to the shared activity buffer */
                                173                 :           1796 :     BackendActivityBufferSize = mul_size(pgstat_track_activity_query_size,
  733 rhaas@postgresql.org      174                 :            898 :                                          NumBackendStatSlots);
 1107 andres@anarazel.de        175                 :            898 :     BackendActivityBuffer = (char *)
                                176                 :            898 :         ShmemInitStruct("Backend Activity Buffer",
                                177                 :                :                         BackendActivityBufferSize,
                                178                 :                :                         &found);
                                179                 :                : 
                                180         [ +  - ]:            898 :     if (!found)
                                181                 :                :     {
                                182   [ +  -  +  -  :            898 :         MemSet(BackendActivityBuffer, 0, BackendActivityBufferSize);
                                     +  -  -  +  -  
                                                 - ]
                                183                 :                : 
                                184                 :                :         /* Initialize st_activity pointers. */
                                185                 :            898 :         buffer = BackendActivityBuffer;
  733 rhaas@postgresql.org      186         [ +  + ]:          80720 :         for (i = 0; i < NumBackendStatSlots; i++)
                                187                 :                :         {
 1107 andres@anarazel.de        188                 :          79822 :             BackendStatusArray[i].st_activity_raw = buffer;
                                189                 :          79822 :             buffer += pgstat_track_activity_query_size;
                                190                 :                :         }
                                191                 :                :     }
                                192                 :                : 
                                193                 :                : #ifdef USE_SSL
                                194                 :                :     /* Create or attach to the shared SSL status buffer */
  733 rhaas@postgresql.org      195                 :            898 :     size = mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots);
 1107 andres@anarazel.de        196                 :            898 :     BackendSslStatusBuffer = (PgBackendSSLStatus *)
                                197                 :            898 :         ShmemInitStruct("Backend SSL Status Buffer", size, &found);
                                198                 :                : 
                                199         [ +  - ]:            898 :     if (!found)
                                200                 :                :     {
                                201                 :                :         PgBackendSSLStatus *ptr;
                                202                 :                : 
                                203   [ +  -  +  +  :            898 :         MemSet(BackendSslStatusBuffer, 0, size);
                                     +  -  -  +  -  
                                                 - ]
                                204                 :                : 
                                205                 :                :         /* Initialize st_sslstatus pointers. */
                                206                 :            898 :         ptr = BackendSslStatusBuffer;
  733 rhaas@postgresql.org      207         [ +  + ]:          80720 :         for (i = 0; i < NumBackendStatSlots; i++)
                                208                 :                :         {
 1107 andres@anarazel.de        209                 :          79822 :             BackendStatusArray[i].st_sslstatus = ptr;
                                210                 :          79822 :             ptr++;
                                211                 :                :         }
                                212                 :                :     }
                                213                 :                : #endif
                                214                 :                : 
                                215                 :                : #ifdef ENABLE_GSS
                                216                 :                :     /* Create or attach to the shared GSSAPI status buffer */
  733 rhaas@postgresql.org      217                 :            898 :     size = mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots);
 1107 andres@anarazel.de        218                 :            898 :     BackendGssStatusBuffer = (PgBackendGSSStatus *)
                                219                 :            898 :         ShmemInitStruct("Backend GSS Status Buffer", size, &found);
                                220                 :                : 
                                221         [ +  - ]:            898 :     if (!found)
                                222                 :                :     {
                                223                 :                :         PgBackendGSSStatus *ptr;
                                224                 :                : 
                                225   [ +  -  +  +  :            898 :         MemSet(BackendGssStatusBuffer, 0, size);
                                     +  -  -  +  -  
                                                 - ]
                                226                 :                : 
                                227                 :                :         /* Initialize st_gssstatus pointers. */
                                228                 :            898 :         ptr = BackendGssStatusBuffer;
  733 rhaas@postgresql.org      229         [ +  + ]:          80720 :         for (i = 0; i < NumBackendStatSlots; i++)
                                230                 :                :         {
 1107 andres@anarazel.de        231                 :          79822 :             BackendStatusArray[i].st_gssstatus = ptr;
                                232                 :          79822 :             ptr++;
                                233                 :                :         }
                                234                 :                :     }
                                235                 :                : #endif
                                236                 :            898 : }
                                237                 :                : 
                                238                 :                : /*
                                239                 :                :  * Initialize pgstats backend activity state, and set up our on-proc-exit
                                240                 :                :  * hook.  Called from InitPostgres and AuxiliaryProcessMain.  MyProcNumber must
                                241                 :                :  * be set, but we must not have started any transaction yet (since the exit
                                242                 :                :  * hook must run after the last transaction exit).
                                243                 :                :  *
                                244                 :                :  * NOTE: MyDatabaseId isn't set yet; so the shutdown hook has to be careful.
                                245                 :                :  */
                                246                 :                : void
                                247                 :          19569 : pgstat_beinit(void)
                                248                 :                : {
                                249                 :                :     /* Initialize MyBEEntry */
   42 heikki.linnakangas@i      250         [ -  + ]:GNC       19569 :     Assert(MyProcNumber != INVALID_PROC_NUMBER);
                                251   [ +  -  -  + ]:          19569 :     Assert(MyProcNumber >= 0 && MyProcNumber < NumBackendStatSlots);
                                252                 :          19569 :     MyBEEntry = &BackendStatusArray[MyProcNumber];
                                253                 :                : 
                                254                 :                :     /* Set up a process-exit hook to clean up */
 1107 andres@anarazel.de        255                 :CBC       19569 :     on_shmem_exit(pgstat_beshutdown_hook, 0);
                                256                 :          19569 : }
                                257                 :                : 
                                258                 :                : 
                                259                 :                : /* ----------
                                260                 :                :  * pgstat_bestart() -
                                261                 :                :  *
                                262                 :                :  *  Initialize this backend's entry in the PgBackendStatus array.
                                263                 :                :  *  Called from InitPostgres.
                                264                 :                :  *
                                265                 :                :  *  Apart from auxiliary processes, MyDatabaseId, session userid, and
                                266                 :                :  *  application_name must already be set (hence, this cannot be combined
                                267                 :                :  *  with pgstat_beinit).  Note also that we must be inside a transaction
                                268                 :                :  *  if this isn't an aux process, as we may need to do encoding conversion
                                269                 :                :  *  on some strings.
                                270                 :                :  *----------
                                271                 :                :  */
                                272                 :                : void
                                273                 :          19309 : pgstat_bestart(void)
                                274                 :                : {
                                275                 :          19309 :     volatile PgBackendStatus *vbeentry = MyBEEntry;
                                276                 :                :     PgBackendStatus lbeentry;
                                277                 :                : #ifdef USE_SSL
                                278                 :                :     PgBackendSSLStatus lsslstatus;
                                279                 :                : #endif
                                280                 :                : #ifdef ENABLE_GSS
                                281                 :                :     PgBackendGSSStatus lgssstatus;
                                282                 :                : #endif
                                283                 :                : 
                                284                 :                :     /* pgstats state must be initialized from pgstat_beinit() */
                                285         [ -  + ]:          19309 :     Assert(vbeentry != NULL);
                                286                 :                : 
                                287                 :                :     /*
                                288                 :                :      * To minimize the time spent modifying the PgBackendStatus entry, and
                                289                 :                :      * avoid risk of errors inside the critical section, we first copy the
                                290                 :                :      * shared-memory struct to a local variable, then modify the data in the
                                291                 :                :      * local variable, then copy the local variable back to shared memory.
                                292                 :                :      * Only the last step has to be inside the critical section.
                                293                 :                :      *
                                294                 :                :      * Most of the data we copy from shared memory is just going to be
                                295                 :                :      * overwritten, but the struct's not so large that it's worth the
                                296                 :                :      * maintenance hassle to copy only the needful fields.
                                297                 :                :      */
                                298                 :          19309 :     memcpy(&lbeentry,
                                299                 :          19309 :            unvolatize(PgBackendStatus *, vbeentry),
                                300                 :                :            sizeof(PgBackendStatus));
                                301                 :                : 
                                302                 :                :     /* These structs can just start from zeroes each time, though */
                                303                 :                : #ifdef USE_SSL
                                304                 :          19309 :     memset(&lsslstatus, 0, sizeof(lsslstatus));
                                305                 :                : #endif
                                306                 :                : #ifdef ENABLE_GSS
                                307                 :          19309 :     memset(&lgssstatus, 0, sizeof(lgssstatus));
                                308                 :                : #endif
                                309                 :                : 
                                310                 :                :     /*
                                311                 :                :      * Now fill in all the fields of lbeentry, except for strings that are
                                312                 :                :      * out-of-line data.  Those have to be handled separately, below.
                                313                 :                :      */
                                314                 :          19309 :     lbeentry.st_procpid = MyProcPid;
                                315                 :          19309 :     lbeentry.st_backendType = MyBackendType;
                                316                 :          19309 :     lbeentry.st_proc_start_timestamp = MyStartTimestamp;
                                317                 :          19309 :     lbeentry.st_activity_start_timestamp = 0;
                                318                 :          19309 :     lbeentry.st_state_start_timestamp = 0;
                                319                 :          19309 :     lbeentry.st_xact_start_timestamp = 0;
                                320                 :          19309 :     lbeentry.st_databaseid = MyDatabaseId;
                                321                 :                : 
                                322                 :                :     /* We have userid for client-backends, wal-sender and bgworker processes */
                                323         [ +  + ]:          19309 :     if (lbeentry.st_backendType == B_BACKEND
                                324         [ +  + ]:           9318 :         || lbeentry.st_backendType == B_WAL_SENDER
                                325         [ +  + ]:           8289 :         || lbeentry.st_backendType == B_BG_WORKER)
                                326                 :          13415 :         lbeentry.st_userid = GetSessionUserId();
                                327                 :                :     else
                                328                 :           5894 :         lbeentry.st_userid = InvalidOid;
                                329                 :                : 
                                330                 :                :     /*
                                331                 :                :      * We may not have a MyProcPort (eg, if this is the autovacuum process).
                                332                 :                :      * If so, use all-zeroes client address, which is dealt with specially in
                                333                 :                :      * pg_stat_get_backend_client_addr and pg_stat_get_backend_client_port.
                                334                 :                :      */
                                335         [ +  + ]:          19309 :     if (MyProcPort)
                                336                 :          11020 :         memcpy(&lbeentry.st_clientaddr, &MyProcPort->raddr,
                                337                 :                :                sizeof(lbeentry.st_clientaddr));
                                338                 :                :     else
                                339   [ +  -  +  -  :         149202 :         MemSet(&lbeentry.st_clientaddr, 0, sizeof(lbeentry.st_clientaddr));
                                     +  -  +  -  +  
                                                 + ]
                                340                 :                : 
                                341                 :                : #ifdef USE_SSL
                                342   [ +  +  +  + ]:          19309 :     if (MyProcPort && MyProcPort->ssl_in_use)
                                343                 :                :     {
                                344                 :            127 :         lbeentry.st_ssl = true;
                                345                 :            127 :         lsslstatus.ssl_bits = be_tls_get_cipher_bits(MyProcPort);
                                346                 :            127 :         strlcpy(lsslstatus.ssl_version, be_tls_get_version(MyProcPort), NAMEDATALEN);
                                347                 :            127 :         strlcpy(lsslstatus.ssl_cipher, be_tls_get_cipher(MyProcPort), NAMEDATALEN);
                                348                 :            127 :         be_tls_get_peer_subject_name(MyProcPort, lsslstatus.ssl_client_dn, NAMEDATALEN);
                                349                 :            127 :         be_tls_get_peer_serial(MyProcPort, lsslstatus.ssl_client_serial, NAMEDATALEN);
                                350                 :            127 :         be_tls_get_peer_issuer_name(MyProcPort, lsslstatus.ssl_issuer_dn, NAMEDATALEN);
                                351                 :                :     }
                                352                 :                :     else
                                353                 :                :     {
                                354                 :          19182 :         lbeentry.st_ssl = false;
                                355                 :                :     }
                                356                 :                : #else
                                357                 :                :     lbeentry.st_ssl = false;
                                358                 :                : #endif
                                359                 :                : 
                                360                 :                : #ifdef ENABLE_GSS
                                361   [ +  +  +  + ]:          19309 :     if (MyProcPort && MyProcPort->gss != NULL)
                                362                 :            160 :     {
                                363                 :            160 :         const char *princ = be_gssapi_get_princ(MyProcPort);
                                364                 :                : 
                                365                 :            160 :         lbeentry.st_gss = true;
                                366                 :            160 :         lgssstatus.gss_auth = be_gssapi_get_auth(MyProcPort);
                                367                 :            160 :         lgssstatus.gss_enc = be_gssapi_get_enc(MyProcPort);
  330 bruce@momjian.us          368                 :            160 :         lgssstatus.gss_delegation = be_gssapi_get_delegation(MyProcPort);
 1107 andres@anarazel.de        369         [ +  + ]:            160 :         if (princ)
                                370                 :             39 :             strlcpy(lgssstatus.gss_princ, princ, NAMEDATALEN);
                                371                 :                :     }
                                372                 :                :     else
                                373                 :                :     {
                                374                 :          19149 :         lbeentry.st_gss = false;
                                375                 :                :     }
                                376                 :                : #else
                                377                 :                :     lbeentry.st_gss = false;
                                378                 :                : #endif
                                379                 :                : 
                                380                 :          19309 :     lbeentry.st_state = STATE_UNDEFINED;
                                381                 :          19309 :     lbeentry.st_progress_command = PROGRESS_COMMAND_INVALID;
                                382                 :          19309 :     lbeentry.st_progress_command_target = InvalidOid;
 1090 bruce@momjian.us          383                 :          19309 :     lbeentry.st_query_id = UINT64CONST(0);
                                384                 :                : 
                                385                 :                :     /*
                                386                 :                :      * we don't zero st_progress_param here to save cycles; nobody should
                                387                 :                :      * examine it until st_progress_command has been set to something other
                                388                 :                :      * than PROGRESS_COMMAND_INVALID
                                389                 :                :      */
                                390                 :                : 
                                391                 :                :     /*
                                392                 :                :      * We're ready to enter the critical section that fills the shared-memory
                                393                 :                :      * status entry.  We follow the protocol of bumping st_changecount before
                                394                 :                :      * and after; and make sure it's even afterwards.  We use a volatile
                                395                 :                :      * pointer here to ensure the compiler doesn't try to get cute.
                                396                 :                :      */
 1107 andres@anarazel.de        397                 :          19309 :     PGSTAT_BEGIN_WRITE_ACTIVITY(vbeentry);
                                398                 :                : 
                                399                 :                :     /* make sure we'll memcpy the same st_changecount back */
                                400                 :          19309 :     lbeentry.st_changecount = vbeentry->st_changecount;
                                401                 :                : 
                                402                 :          19309 :     memcpy(unvolatize(PgBackendStatus *, vbeentry),
                                403                 :                :            &lbeentry,
                                404                 :                :            sizeof(PgBackendStatus));
                                405                 :                : 
                                406                 :                :     /*
                                407                 :                :      * We can write the out-of-line strings and structs using the pointers
                                408                 :                :      * that are in lbeentry; this saves some de-volatilizing messiness.
                                409                 :                :      */
                                410                 :          19309 :     lbeentry.st_appname[0] = '\0';
                                411   [ +  +  +  + ]:          19309 :     if (MyProcPort && MyProcPort->remote_hostname)
                                412                 :             76 :         strlcpy(lbeentry.st_clienthostname, MyProcPort->remote_hostname,
                                413                 :                :                 NAMEDATALEN);
                                414                 :                :     else
                                415                 :          19233 :         lbeentry.st_clienthostname[0] = '\0';
                                416                 :          19309 :     lbeentry.st_activity_raw[0] = '\0';
                                417                 :                :     /* Also make sure the last byte in each string area is always 0 */
                                418                 :          19309 :     lbeentry.st_appname[NAMEDATALEN - 1] = '\0';
                                419                 :          19309 :     lbeentry.st_clienthostname[NAMEDATALEN - 1] = '\0';
                                420                 :          19309 :     lbeentry.st_activity_raw[pgstat_track_activity_query_size - 1] = '\0';
                                421                 :                : 
                                422                 :                : #ifdef USE_SSL
                                423                 :          19309 :     memcpy(lbeentry.st_sslstatus, &lsslstatus, sizeof(PgBackendSSLStatus));
                                424                 :                : #endif
                                425                 :                : #ifdef ENABLE_GSS
                                426                 :          19309 :     memcpy(lbeentry.st_gssstatus, &lgssstatus, sizeof(PgBackendGSSStatus));
                                427                 :                : #endif
                                428                 :                : 
                                429   [ -  +  -  + ]:          19309 :     PGSTAT_END_WRITE_ACTIVITY(vbeentry);
                                430                 :                : 
                                431                 :                :     /* Update app name to current GUC setting */
                                432         [ +  - ]:          19309 :     if (application_name)
                                433                 :          19309 :         pgstat_report_appname(application_name);
                                434                 :          19309 : }
                                435                 :                : 
                                436                 :                : /*
                                437                 :                :  * Clear out our entry in the PgBackendStatus array.
                                438                 :                :  */
                                439                 :                : static void
                                440                 :          18040 : pgstat_beshutdown_hook(int code, Datum arg)
                                441                 :                : {
                                442                 :          18040 :     volatile PgBackendStatus *beentry = MyBEEntry;
                                443                 :                : 
                                444                 :                :     /*
                                445                 :                :      * Clear my status entry, following the protocol of bumping st_changecount
                                446                 :                :      * before and after.  We use a volatile pointer here to ensure the
                                447                 :                :      * compiler doesn't try to get cute.
                                448                 :                :      */
                                449                 :          18040 :     PGSTAT_BEGIN_WRITE_ACTIVITY(beentry);
                                450                 :                : 
                                451                 :          18040 :     beentry->st_procpid = 0; /* mark invalid */
                                452                 :                : 
                                453   [ -  +  -  + ]:          18040 :     PGSTAT_END_WRITE_ACTIVITY(beentry);
                                454                 :                : 
                                455                 :                :     /* so that functions can check if backend_status.c is up via MyBEEntry */
  969                           456                 :          18040 :     MyBEEntry = NULL;
 1107                           457                 :          18040 : }
                                458                 :                : 
                                459                 :                : /*
                                460                 :                :  * Discard any data collected in the current transaction.  Any subsequent
                                461                 :                :  * request will cause new snapshots to be read.
                                462                 :                :  *
                                463                 :                :  * This is also invoked during transaction commit or abort to discard the
                                464                 :                :  * no-longer-wanted snapshot.
                                465                 :                :  */
                                466                 :                : void
                                467                 :         433341 : pgstat_clear_backend_activity_snapshot(void)
                                468                 :                : {
                                469                 :                :     /* Release memory, if any was allocated */
                                470         [ +  + ]:         433341 :     if (backendStatusSnapContext)
                                471                 :                :     {
                                472                 :           1040 :         MemoryContextDelete(backendStatusSnapContext);
                                473                 :           1040 :         backendStatusSnapContext = NULL;
                                474                 :                :     }
                                475                 :                : 
                                476                 :                :     /* Reset variables */
                                477                 :         433341 :     localBackendStatusTable = NULL;
                                478                 :         433341 :     localNumBackends = 0;
                                479                 :         433341 : }
                                480                 :                : 
                                481                 :                : static void
                                482                 :           1040 : pgstat_setup_backend_status_context(void)
                                483                 :                : {
                                484         [ +  - ]:           1040 :     if (!backendStatusSnapContext)
                                485                 :           1040 :         backendStatusSnapContext = AllocSetContextCreate(TopMemoryContext,
                                486                 :                :                                                          "Backend Status Snapshot",
                                487                 :                :                                                          ALLOCSET_SMALL_SIZES);
                                488                 :           1040 : }
                                489                 :                : 
                                490                 :                : 
                                491                 :                : /* ----------
                                492                 :                :  * pgstat_report_activity() -
                                493                 :                :  *
                                494                 :                :  *  Called from tcop/postgres.c to report what the backend is actually doing
                                495                 :                :  *  (but note cmd_str can be NULL for certain cases).
                                496                 :                :  *
                                497                 :                :  * All updates of the status entry follow the protocol of bumping
                                498                 :                :  * st_changecount before and after.  We use a volatile pointer here to
                                499                 :                :  * ensure the compiler doesn't try to get cute.
                                500                 :                :  * ----------
                                501                 :                :  */
                                502                 :                : void
                                503                 :         703880 : pgstat_report_activity(BackendState state, const char *cmd_str)
                                504                 :                : {
                                505                 :         703880 :     volatile PgBackendStatus *beentry = MyBEEntry;
                                506                 :                :     TimestampTz start_timestamp;
                                507                 :                :     TimestampTz current_timestamp;
                                508                 :         703880 :     int         len = 0;
                                509                 :                : 
                                510                 :                :     TRACE_POSTGRESQL_STATEMENT_STATUS(cmd_str);
                                511                 :                : 
                                512         [ -  + ]:         703880 :     if (!beentry)
 1107 andres@anarazel.de        513                 :UBC           0 :         return;
                                514                 :                : 
 1107 andres@anarazel.de        515         [ -  + ]:CBC      703880 :     if (!pgstat_track_activities)
                                516                 :                :     {
 1107 andres@anarazel.de        517         [ #  # ]:UBC           0 :         if (beentry->st_state != STATE_DISABLED)
                                518                 :                :         {
                                519                 :              0 :             volatile PGPROC *proc = MyProc;
                                520                 :                : 
                                521                 :                :             /*
                                522                 :                :              * track_activities is disabled, but we last reported a
                                523                 :                :              * non-disabled state.  As our final update, change the state and
                                524                 :                :              * clear fields we will not be updating anymore.
                                525                 :                :              */
                                526                 :              0 :             PGSTAT_BEGIN_WRITE_ACTIVITY(beentry);
                                527                 :              0 :             beentry->st_state = STATE_DISABLED;
                                528                 :              0 :             beentry->st_state_start_timestamp = 0;
                                529                 :              0 :             beentry->st_activity_raw[0] = '\0';
                                530                 :              0 :             beentry->st_activity_start_timestamp = 0;
                                531                 :                :             /* st_xact_start_timestamp and wait_event_info are also disabled */
                                532                 :              0 :             beentry->st_xact_start_timestamp = 0;
 1090 bruce@momjian.us          533                 :              0 :             beentry->st_query_id = UINT64CONST(0);
 1107 andres@anarazel.de        534                 :              0 :             proc->wait_event_info = 0;
                                535   [ #  #  #  # ]:              0 :             PGSTAT_END_WRITE_ACTIVITY(beentry);
                                536                 :                :         }
                                537                 :              0 :         return;
                                538                 :                :     }
                                539                 :                : 
                                540                 :                :     /*
                                541                 :                :      * To minimize the time spent modifying the entry, and avoid risk of
                                542                 :                :      * errors inside the critical section, fetch all the needed data first.
                                543                 :                :      */
 1107 andres@anarazel.de        544                 :CBC      703880 :     start_timestamp = GetCurrentStatementStartTimestamp();
                                545         [ +  + ]:         703880 :     if (cmd_str != NULL)
                                546                 :                :     {
                                547                 :                :         /*
                                548                 :                :          * Compute length of to-be-stored string unaware of multi-byte
                                549                 :                :          * characters. For speed reasons that'll get corrected on read, rather
                                550                 :                :          * than computed every write.
                                551                 :                :          */
                                552         [ +  + ]:         388276 :         len = Min(strlen(cmd_str), pgstat_track_activity_query_size - 1);
                                553                 :                :     }
                                554                 :         703880 :     current_timestamp = GetCurrentTimestamp();
                                555                 :                : 
                                556                 :                :     /*
                                557                 :                :      * If the state has changed from "active" or "idle in transaction",
                                558                 :                :      * calculate the duration.
                                559                 :                :      */
                                560         [ +  + ]:         703880 :     if ((beentry->st_state == STATE_RUNNING ||
                                561         [ +  + ]:         316590 :          beentry->st_state == STATE_FASTPATH ||
                                562         [ +  + ]:         315527 :          beentry->st_state == STATE_IDLEINTRANSACTION ||
                                563         [ +  + ]:         249158 :          beentry->st_state == STATE_IDLEINTRANSACTION_ABORTED) &&
                                564         [ +  + ]:         455556 :         state != beentry->st_state)
                                565                 :                :     {
                                566                 :                :         long        secs;
                                567                 :                :         int         usecs;
                                568                 :                : 
                                569                 :         368811 :         TimestampDifference(beentry->st_state_start_timestamp,
                                570                 :                :                             current_timestamp,
                                571                 :                :                             &secs, &usecs);
                                572                 :                : 
                                573         [ +  + ]:         368811 :         if (beentry->st_state == STATE_RUNNING ||
                                574         [ +  + ]:          68259 :             beentry->st_state == STATE_FASTPATH)
  941                           575                 :         301615 :             pgstat_count_conn_active_time((PgStat_Counter) secs * 1000000 + usecs);
                                576                 :                :         else
                                577                 :          67196 :             pgstat_count_conn_txn_idle_time((PgStat_Counter) secs * 1000000 + usecs);
                                578                 :                :     }
                                579                 :                : 
                                580                 :                :     /*
                                581                 :                :      * Now update the status entry
                                582                 :                :      */
 1107                           583                 :         703880 :     PGSTAT_BEGIN_WRITE_ACTIVITY(beentry);
                                584                 :                : 
                                585                 :         703880 :     beentry->st_state = state;
                                586                 :         703880 :     beentry->st_state_start_timestamp = current_timestamp;
                                587                 :                : 
                                588                 :                :     /*
                                589                 :                :      * If a new query is started, we reset the query identifier as it'll only
                                590                 :                :      * be known after parse analysis, to avoid reporting last query's
                                591                 :                :      * identifier.
                                592                 :                :      */
 1103 bruce@momjian.us          593         [ +  + ]:         703880 :     if (state == STATE_RUNNING)
 1090                           594                 :         389657 :         beentry->st_query_id = UINT64CONST(0);
                                595                 :                : 
 1107 andres@anarazel.de        596         [ +  + ]:         703880 :     if (cmd_str != NULL)
                                597                 :                :     {
                                598                 :         388276 :         memcpy((char *) beentry->st_activity_raw, cmd_str, len);
                                599                 :         388276 :         beentry->st_activity_raw[len] = '\0';
                                600                 :         388276 :         beentry->st_activity_start_timestamp = start_timestamp;
                                601                 :                :     }
                                602                 :                : 
                                603   [ -  +  -  + ]:         703880 :     PGSTAT_END_WRITE_ACTIVITY(beentry);
                                604                 :                : }
                                605                 :                : 
                                606                 :                : /* --------
                                607                 :                :  * pgstat_report_query_id() -
                                608                 :                :  *
                                609                 :                :  * Called to update top-level query identifier.
                                610                 :                :  * --------
                                611                 :                :  */
                                612                 :                : void
 1090 bruce@momjian.us          613                 :         979368 : pgstat_report_query_id(uint64 query_id, bool force)
                                614                 :                : {
 1103                           615                 :         979368 :     volatile PgBackendStatus *beentry = MyBEEntry;
                                616                 :                : 
                                617                 :                :     /*
                                618                 :                :      * if track_activities is disabled, st_query_id should already have been
                                619                 :                :      * reset
                                620                 :                :      */
                                621   [ +  -  -  + ]:         979368 :     if (!beentry || !pgstat_track_activities)
 1103 bruce@momjian.us          622                 :UBC           0 :         return;
                                623                 :                : 
                                624                 :                :     /*
                                625                 :                :      * We only report the top-level query identifiers.  The stored query_id is
                                626                 :                :      * reset when a backend calls pgstat_report_activity(STATE_RUNNING), or
                                627                 :                :      * with an explicit call to this function using the force flag.  If the
                                628                 :                :      * saved query identifier is not zero it means that it's not a top-level
                                629                 :                :      * command, so ignore the one provided unless it's an explicit call to
                                630                 :                :      * reset the identifier.
                                631                 :                :      */
 1090 bruce@momjian.us          632   [ +  +  +  + ]:CBC      979368 :     if (beentry->st_query_id != 0 && !force)
 1103                           633                 :          54671 :         return;
                                634                 :                : 
                                635                 :                :     /*
                                636                 :                :      * Update my status entry, following the protocol of bumping
                                637                 :                :      * st_changecount before and after.  We use a volatile pointer here to
                                638                 :                :      * ensure the compiler doesn't try to get cute.
                                639                 :                :      */
                                640                 :         924697 :     PGSTAT_BEGIN_WRITE_ACTIVITY(beentry);
 1090                           641                 :         924697 :     beentry->st_query_id = query_id;
 1103                           642   [ -  +  -  + ]:         924697 :     PGSTAT_END_WRITE_ACTIVITY(beentry);
                                643                 :                : }
                                644                 :                : 
                                645                 :                : 
                                646                 :                : /* ----------
                                647                 :                :  * pgstat_report_appname() -
                                648                 :                :  *
                                649                 :                :  *  Called to update our application name.
                                650                 :                :  * ----------
                                651                 :                :  */
                                652                 :                : void
 1107 andres@anarazel.de        653                 :          33029 : pgstat_report_appname(const char *appname)
                                654                 :                : {
                                655                 :          33029 :     volatile PgBackendStatus *beentry = MyBEEntry;
                                656                 :                :     int         len;
                                657                 :                : 
                                658         [ +  + ]:          33029 :     if (!beentry)
                                659                 :            928 :         return;
                                660                 :                : 
                                661                 :                :     /* This should be unnecessary if GUC did its job, but be safe */
                                662                 :          32101 :     len = pg_mbcliplen(appname, strlen(appname), NAMEDATALEN - 1);
                                663                 :                : 
                                664                 :                :     /*
                                665                 :                :      * Update my status entry, following the protocol of bumping
                                666                 :                :      * st_changecount before and after.  We use a volatile pointer here to
                                667                 :                :      * ensure the compiler doesn't try to get cute.
                                668                 :                :      */
                                669                 :          32101 :     PGSTAT_BEGIN_WRITE_ACTIVITY(beentry);
                                670                 :                : 
                                671                 :          32101 :     memcpy((char *) beentry->st_appname, appname, len);
                                672                 :          32101 :     beentry->st_appname[len] = '\0';
                                673                 :                : 
                                674   [ -  +  -  + ]:          32101 :     PGSTAT_END_WRITE_ACTIVITY(beentry);
                                675                 :                : }
                                676                 :                : 
                                677                 :                : /*
                                678                 :                :  * Report current transaction start timestamp as the specified value.
                                679                 :                :  * Zero means there is no active transaction.
                                680                 :                :  */
                                681                 :                : void
                                682                 :         865848 : pgstat_report_xact_timestamp(TimestampTz tstamp)
                                683                 :                : {
                                684                 :         865848 :     volatile PgBackendStatus *beentry = MyBEEntry;
                                685                 :                : 
                                686   [ +  -  -  + ]:         865848 :     if (!pgstat_track_activities || !beentry)
 1107 andres@anarazel.de        687                 :UBC           0 :         return;
                                688                 :                : 
                                689                 :                :     /*
                                690                 :                :      * Update my status entry, following the protocol of bumping
                                691                 :                :      * st_changecount before and after.  We use a volatile pointer here to
                                692                 :                :      * ensure the compiler doesn't try to get cute.
                                693                 :                :      */
 1107 andres@anarazel.de        694                 :CBC      865848 :     PGSTAT_BEGIN_WRITE_ACTIVITY(beentry);
                                695                 :                : 
                                696                 :         865848 :     beentry->st_xact_start_timestamp = tstamp;
                                697                 :                : 
                                698   [ -  +  -  + ]:         865848 :     PGSTAT_END_WRITE_ACTIVITY(beentry);
                                699                 :                : }
                                700                 :                : 
                                701                 :                : /* ----------
                                702                 :                :  * pgstat_read_current_status() -
                                703                 :                :  *
                                704                 :                :  *  Copy the current contents of the PgBackendStatus array to local memory,
                                705                 :                :  *  if not already done in this transaction.
                                706                 :                :  * ----------
                                707                 :                :  */
                                708                 :                : static void
                                709                 :          10219 : pgstat_read_current_status(void)
                                710                 :                : {
                                711                 :                :     volatile PgBackendStatus *beentry;
                                712                 :                :     LocalPgBackendStatus *localtable;
                                713                 :                :     LocalPgBackendStatus *localentry;
                                714                 :                :     char       *localappname,
                                715                 :                :                *localclienthostname,
                                716                 :                :                *localactivity;
                                717                 :                : #ifdef USE_SSL
                                718                 :                :     PgBackendSSLStatus *localsslstatus;
                                719                 :                : #endif
                                720                 :                : #ifdef ENABLE_GSS
                                721                 :                :     PgBackendGSSStatus *localgssstatus;
                                722                 :                : #endif
                                723                 :                :     ProcNumber  procNumber;
                                724                 :                : 
                                725         [ +  + ]:          10219 :     if (localBackendStatusTable)
                                726                 :           9179 :         return;                 /* already done */
                                727                 :                : 
                                728                 :           1040 :     pgstat_setup_backend_status_context();
                                729                 :                : 
                                730                 :                :     /*
                                731                 :                :      * Allocate storage for local copy of state data.  We can presume that
                                732                 :                :      * none of these requests overflow size_t, because we already calculated
                                733                 :                :      * the same values using mul_size during shmem setup.  However, with
                                734                 :                :      * probably-silly values of pgstat_track_activity_query_size and
                                735                 :                :      * max_connections, the localactivity buffer could exceed 1GB, so use
                                736                 :                :      * "huge" allocation for that one.
                                737                 :                :      */
                                738                 :                :     localtable = (LocalPgBackendStatus *)
                                739                 :           1040 :         MemoryContextAlloc(backendStatusSnapContext,
  733 rhaas@postgresql.org      740                 :           1040 :                            sizeof(LocalPgBackendStatus) * NumBackendStatSlots);
                                741                 :                :     localappname = (char *)
 1107 andres@anarazel.de        742                 :           1040 :         MemoryContextAlloc(backendStatusSnapContext,
  733 rhaas@postgresql.org      743                 :           1040 :                            NAMEDATALEN * NumBackendStatSlots);
                                744                 :                :     localclienthostname = (char *)
 1107 andres@anarazel.de        745                 :           1040 :         MemoryContextAlloc(backendStatusSnapContext,
  733 rhaas@postgresql.org      746                 :           1040 :                            NAMEDATALEN * NumBackendStatSlots);
                                747                 :                :     localactivity = (char *)
 1107 andres@anarazel.de        748                 :           1040 :         MemoryContextAllocHuge(backendStatusSnapContext,
  194 michael@paquier.xyz       749                 :           1040 :                                (Size) pgstat_track_activity_query_size *
                                750                 :           1040 :                                (Size) NumBackendStatSlots);
                                751                 :                : #ifdef USE_SSL
                                752                 :                :     localsslstatus = (PgBackendSSLStatus *)
 1107 andres@anarazel.de        753                 :           1040 :         MemoryContextAlloc(backendStatusSnapContext,
  733 rhaas@postgresql.org      754                 :           1040 :                            sizeof(PgBackendSSLStatus) * NumBackendStatSlots);
                                755                 :                : #endif
                                756                 :                : #ifdef ENABLE_GSS
                                757                 :                :     localgssstatus = (PgBackendGSSStatus *)
 1107 andres@anarazel.de        758                 :           1040 :         MemoryContextAlloc(backendStatusSnapContext,
  733 rhaas@postgresql.org      759                 :           1040 :                            sizeof(PgBackendGSSStatus) * NumBackendStatSlots);
                                760                 :                : #endif
                                761                 :                : 
 1107 andres@anarazel.de        762                 :           1040 :     localNumBackends = 0;
                                763                 :                : 
                                764                 :           1040 :     beentry = BackendStatusArray;
                                765                 :           1040 :     localentry = localtable;
   42 heikki.linnakangas@i      766         [ +  + ]:GNC       67903 :     for (procNumber = 0; procNumber < NumBackendStatSlots; procNumber++)
                                767                 :                :     {
                                768                 :                :         /*
                                769                 :                :          * Follow the protocol of retrying if st_changecount changes while we
                                770                 :                :          * copy the entry, or if it's odd.  (The check for odd is needed to
                                771                 :                :          * cover the case where we are able to completely copy the entry while
                                772                 :                :          * the source backend is between increment steps.)  We use a volatile
                                773                 :                :          * pointer here to ensure the compiler doesn't try to get cute.
                                774                 :                :          */
                                775                 :                :         for (;;)
 1107 andres@anarazel.de        776                 :GBC           1 :         {
                                777                 :                :             int         before_changecount;
                                778                 :                :             int         after_changecount;
                                779                 :                : 
 1107 andres@anarazel.de        780                 :CBC       66864 :             pgstat_begin_read_activity(beentry, before_changecount);
                                781                 :                : 
                                782                 :          66864 :             localentry->backendStatus.st_procpid = beentry->st_procpid;
                                783                 :                :             /* Skip all the data-copying work if entry is not in use */
                                784         [ +  + ]:          66864 :             if (localentry->backendStatus.st_procpid > 0)
                                785                 :                :             {
                                786                 :           7286 :                 memcpy(&localentry->backendStatus, unvolatize(PgBackendStatus *, beentry), sizeof(PgBackendStatus));
                                787                 :                : 
                                788                 :                :                 /*
                                789                 :                :                  * For each PgBackendStatus field that is a pointer, copy the
                                790                 :                :                  * pointed-to data, then adjust the local copy of the pointer
                                791                 :                :                  * field to point at the local copy of the data.
                                792                 :                :                  *
                                793                 :                :                  * strcpy is safe even if the string is modified concurrently,
                                794                 :                :                  * because there's always a \0 at the end of the buffer.
                                795                 :                :                  */
                                796                 :           7286 :                 strcpy(localappname, (char *) beentry->st_appname);
                                797                 :           7286 :                 localentry->backendStatus.st_appname = localappname;
                                798                 :           7286 :                 strcpy(localclienthostname, (char *) beentry->st_clienthostname);
                                799                 :           7286 :                 localentry->backendStatus.st_clienthostname = localclienthostname;
                                800                 :           7286 :                 strcpy(localactivity, (char *) beentry->st_activity_raw);
                                801                 :           7286 :                 localentry->backendStatus.st_activity_raw = localactivity;
                                802                 :                : #ifdef USE_SSL
                                803         [ +  + ]:           7286 :                 if (beentry->st_ssl)
                                804                 :                :                 {
                                805                 :             58 :                     memcpy(localsslstatus, beentry->st_sslstatus, sizeof(PgBackendSSLStatus));
                                806                 :             58 :                     localentry->backendStatus.st_sslstatus = localsslstatus;
                                807                 :                :                 }
                                808                 :                : #endif
                                809                 :                : #ifdef ENABLE_GSS
                                810         [ +  + ]:           7286 :                 if (beentry->st_gss)
                                811                 :                :                 {
                                812                 :            137 :                     memcpy(localgssstatus, beentry->st_gssstatus, sizeof(PgBackendGSSStatus));
                                813                 :            137 :                     localentry->backendStatus.st_gssstatus = localgssstatus;
                                814                 :                :                 }
                                815                 :                : #endif
                                816                 :                :             }
                                817                 :                : 
                                818                 :          66864 :             pgstat_end_read_activity(beentry, after_changecount);
                                819                 :                : 
                                820   [ +  +  +  - ]:          66864 :             if (pgstat_read_activity_complete(before_changecount,
                                821                 :                :                                               after_changecount))
                                822                 :          66863 :                 break;
                                823                 :                : 
                                824                 :                :             /* Make sure we can break out of loop if stuck... */
 1107 andres@anarazel.de        825         [ -  + ]:GBC           1 :             CHECK_FOR_INTERRUPTS();
                                826                 :                :         }
                                827                 :                : 
                                828                 :                :         /* Only valid entries get included into the local array */
 1107 andres@anarazel.de        829         [ +  + ]:CBC       66863 :         if (localentry->backendStatus.st_procpid > 0)
                                830                 :                :         {
                                831                 :                :             /*
                                832                 :                :              * The BackendStatusArray index is exactly the ProcNumber of the
                                833                 :                :              * source backend.  Note that this means localBackendStatusTable
                                834                 :                :              * is in order by proc_number. pgstat_get_beentry_by_proc_number()
                                835                 :                :              * depends on that.
                                836                 :                :              */
   42 heikki.linnakangas@i      837                 :GNC        7285 :             localentry->proc_number = procNumber;
                                838                 :           7285 :             ProcNumberGetTransactionIds(procNumber,
                                839                 :                :                                         &localentry->backend_xid,
                                840                 :                :                                         &localentry->backend_xmin,
                                841                 :                :                                         &localentry->backend_subxact_count,
                                842                 :                :                                         &localentry->backend_subxact_overflowed);
                                843                 :                : 
 1107 andres@anarazel.de        844                 :CBC        7285 :             localentry++;
                                845                 :           7285 :             localappname += NAMEDATALEN;
                                846                 :           7285 :             localclienthostname += NAMEDATALEN;
                                847                 :           7285 :             localactivity += pgstat_track_activity_query_size;
                                848                 :                : #ifdef USE_SSL
                                849                 :           7285 :             localsslstatus++;
                                850                 :                : #endif
                                851                 :                : #ifdef ENABLE_GSS
                                852                 :           7285 :             localgssstatus++;
                                853                 :                : #endif
                                854                 :           7285 :             localNumBackends++;
                                855                 :                :         }
                                856                 :                : 
  481 john.naylor@postgres      857                 :          66863 :         beentry++;
                                858                 :                :     }
                                859                 :                : 
                                860                 :                :     /* Set the pointer only after completion of a valid table */
 1107 andres@anarazel.de        861                 :           1040 :     localBackendStatusTable = localtable;
                                862                 :                : }
                                863                 :                : 
                                864                 :                : 
                                865                 :                : /* ----------
                                866                 :                :  * pgstat_get_backend_current_activity() -
                                867                 :                :  *
                                868                 :                :  *  Return a string representing the current activity of the backend with
                                869                 :                :  *  the specified PID.  This looks directly at the BackendStatusArray,
                                870                 :                :  *  and so will provide current information regardless of the age of our
                                871                 :                :  *  transaction's snapshot of the status array.
                                872                 :                :  *
                                873                 :                :  *  It is the caller's responsibility to invoke this only for backends whose
                                874                 :                :  *  state is expected to remain stable while the result is in use.  The
                                875                 :                :  *  only current use is in deadlock reporting, where we can expect that
                                876                 :                :  *  the target backend is blocked on a lock.  (There are corner cases
                                877                 :                :  *  where the target's wait could get aborted while we are looking at it,
                                878                 :                :  *  but the very worst consequence is to return a pointer to a string
                                879                 :                :  *  that's been changed, so we won't worry too much.)
                                880                 :                :  *
                                881                 :                :  *  Note: return strings for special cases match pg_stat_get_backend_activity.
                                882                 :                :  * ----------
                                883                 :                :  */
                                884                 :                : const char *
                                885                 :             17 : pgstat_get_backend_current_activity(int pid, bool checkUser)
                                886                 :                : {
                                887                 :                :     PgBackendStatus *beentry;
                                888                 :                :     int         i;
                                889                 :                : 
                                890                 :             17 :     beentry = BackendStatusArray;
  733 rhaas@postgresql.org      891         [ +  - ]:           1513 :     for (i = 1; i <= MaxBackends; i++)
                                892                 :                :     {
                                893                 :                :         /*
                                894                 :                :          * Although we expect the target backend's entry to be stable, that
                                895                 :                :          * doesn't imply that anyone else's is.  To avoid identifying the
                                896                 :                :          * wrong backend, while we check for a match to the desired PID we
                                897                 :                :          * must follow the protocol of retrying if st_changecount changes
                                898                 :                :          * while we examine the entry, or if it's odd.  (This might be
                                899                 :                :          * unnecessary, since fetching or storing an int is almost certainly
                                900                 :                :          * atomic, but let's play it safe.)  We use a volatile pointer here to
                                901                 :                :          * ensure the compiler doesn't try to get cute.
                                902                 :                :          */
 1107 andres@anarazel.de        903                 :           1513 :         volatile PgBackendStatus *vbeentry = beentry;
                                904                 :                :         bool        found;
                                905                 :                : 
                                906                 :                :         for (;;)
 1107 andres@anarazel.de        907                 :UBC           0 :         {
                                908                 :                :             int         before_changecount;
                                909                 :                :             int         after_changecount;
                                910                 :                : 
 1107 andres@anarazel.de        911                 :CBC        1513 :             pgstat_begin_read_activity(vbeentry, before_changecount);
                                912                 :                : 
                                913                 :           1513 :             found = (vbeentry->st_procpid == pid);
                                914                 :                : 
                                915                 :           1513 :             pgstat_end_read_activity(vbeentry, after_changecount);
                                916                 :                : 
                                917   [ +  -  +  - ]:           1513 :             if (pgstat_read_activity_complete(before_changecount,
                                918                 :                :                                               after_changecount))
                                919                 :           1513 :                 break;
                                920                 :                : 
                                921                 :                :             /* Make sure we can break out of loop if stuck... */
 1107 andres@anarazel.de        922         [ #  # ]:UBC           0 :             CHECK_FOR_INTERRUPTS();
                                923                 :                :         }
                                924                 :                : 
 1107 andres@anarazel.de        925         [ +  + ]:CBC        1513 :         if (found)
                                926                 :                :         {
                                927                 :                :             /* Now it is safe to use the non-volatile pointer */
                                928   [ -  +  -  -  :             17 :             if (checkUser && !superuser() && beentry->st_userid != GetUserId())
                                              -  - ]
 1107 andres@anarazel.de        929                 :UBC           0 :                 return "<insufficient privilege>";
 1107 andres@anarazel.de        930         [ +  + ]:CBC          17 :             else if (*(beentry->st_activity_raw) == '\0')
                                931                 :              5 :                 return "<command string not enabled>";
                                932                 :                :             else
                                933                 :                :             {
                                934                 :                :                 /* this'll leak a bit of memory, but that seems acceptable */
                                935                 :             12 :                 return pgstat_clip_activity(beentry->st_activity_raw);
                                936                 :                :             }
                                937                 :                :         }
                                938                 :                : 
                                939                 :           1496 :         beentry++;
                                940                 :                :     }
                                941                 :                : 
                                942                 :                :     /* If we get here, caller is in error ... */
 1107 andres@anarazel.de        943                 :UBC           0 :     return "<backend information not available>";
                                944                 :                : }
                                945                 :                : 
                                946                 :                : /* ----------
                                947                 :                :  * pgstat_get_crashed_backend_activity() -
                                948                 :                :  *
                                949                 :                :  *  Return a string representing the current activity of the backend with
                                950                 :                :  *  the specified PID.  Like the function above, but reads shared memory with
                                951                 :                :  *  the expectation that it may be corrupt.  On success, copy the string
                                952                 :                :  *  into the "buffer" argument and return that pointer.  On failure,
                                953                 :                :  *  return NULL.
                                954                 :                :  *
                                955                 :                :  *  This function is only intended to be used by the postmaster to report the
                                956                 :                :  *  query that crashed a backend.  In particular, no attempt is made to
                                957                 :                :  *  follow the correct concurrency protocol when accessing the
                                958                 :                :  *  BackendStatusArray.  But that's OK, in the worst case we'll return a
                                959                 :                :  *  corrupted message.  We also must take care not to trip on ereport(ERROR).
                                960                 :                :  * ----------
                                961                 :                :  */
                                962                 :                : const char *
 1107 andres@anarazel.de        963                 :CBC        1248 : pgstat_get_crashed_backend_activity(int pid, char *buffer, int buflen)
                                964                 :                : {
                                965                 :                :     volatile PgBackendStatus *beentry;
                                966                 :                :     int         i;
                                967                 :                : 
                                968                 :           1248 :     beentry = BackendStatusArray;
                                969                 :                : 
                                970                 :                :     /*
                                971                 :                :      * We probably shouldn't get here before shared memory has been set up,
                                972                 :                :      * but be safe.
                                973                 :                :      */
                                974   [ +  -  -  + ]:           1248 :     if (beentry == NULL || BackendActivityBuffer == NULL)
 1107 andres@anarazel.de        975                 :UBC           0 :         return NULL;
                                976                 :                : 
  733 rhaas@postgresql.org      977         [ +  + ]:CBC      116317 :     for (i = 1; i <= MaxBackends; i++)
                                978                 :                :     {
 1107 andres@anarazel.de        979         [ +  + ]:         115135 :         if (beentry->st_procpid == pid)
                                980                 :                :         {
                                981                 :                :             /* Read pointer just once, so it can't change after validation */
                                982                 :             66 :             const char *activity = beentry->st_activity_raw;
                                983                 :                :             const char *activity_last;
                                984                 :                : 
                                985                 :                :             /*
                                986                 :                :              * We mustn't access activity string before we verify that it
                                987                 :                :              * falls within the BackendActivityBuffer. To make sure that the
                                988                 :                :              * entire string including its ending is contained within the
                                989                 :                :              * buffer, subtract one activity length from the buffer size.
                                990                 :                :              */
                                991                 :             66 :             activity_last = BackendActivityBuffer + BackendActivityBufferSize
                                992                 :             66 :                 - pgstat_track_activity_query_size;
                                993                 :                : 
                                994   [ +  -  -  + ]:             66 :             if (activity < BackendActivityBuffer ||
                                995                 :                :                 activity > activity_last)
 1107 andres@anarazel.de        996                 :UBC           0 :                 return NULL;
                                997                 :                : 
                                998                 :                :             /* If no string available, no point in a report */
 1107 andres@anarazel.de        999         [ -  + ]:CBC          66 :             if (activity[0] == '\0')
 1107 andres@anarazel.de       1000                 :UBC           0 :                 return NULL;
                               1001                 :                : 
                               1002                 :                :             /*
                               1003                 :                :              * Copy only ASCII-safe characters so we don't run into encoding
                               1004                 :                :              * problems when reporting the message; and be sure not to run off
                               1005                 :                :              * the end of memory.  As only ASCII characters are reported, it
                               1006                 :                :              * doesn't seem necessary to perform multibyte aware clipping.
                               1007                 :                :              */
 1107 andres@anarazel.de       1008                 :CBC          66 :             ascii_safe_strlcpy(buffer, activity,
                               1009                 :             66 :                                Min(buflen, pgstat_track_activity_query_size));
                               1010                 :                : 
                               1011                 :             66 :             return buffer;
                               1012                 :                :         }
                               1013                 :                : 
                               1014                 :         115069 :         beentry++;
                               1015                 :                :     }
                               1016                 :                : 
                               1017                 :                :     /* PID not found */
                               1018                 :           1182 :     return NULL;
                               1019                 :                : }
                               1020                 :                : 
                               1021                 :                : /* ----------
                               1022                 :                :  * pgstat_get_my_query_id() -
                               1023                 :                :  *
                               1024                 :                :  * Return current backend's query identifier.
                               1025                 :                :  */
                               1026                 :                : uint64
 1090 bruce@momjian.us         1027                 :            372 : pgstat_get_my_query_id(void)
                               1028                 :                : {
 1103                          1029         [ +  + ]:            372 :     if (!MyBEEntry)
                               1030                 :             14 :         return 0;
                               1031                 :                : 
                               1032                 :                :     /*
                               1033                 :                :      * There's no need for a lock around pgstat_begin_read_activity /
                               1034                 :                :      * pgstat_end_read_activity here as it's only called from
                               1035                 :                :      * pg_stat_get_activity which is already protected, or from the same
                               1036                 :                :      * backend which means that there won't be concurrent writes.
                               1037                 :                :      */
 1090                          1038                 :            358 :     return MyBEEntry->st_query_id;
                               1039                 :                : }
                               1040                 :                : 
                               1041                 :                : /* ----------
                               1042                 :                :  * cmp_lbestatus
                               1043                 :                :  *
                               1044                 :                :  *  Comparison function for bsearch() on an array of LocalPgBackendStatus.
                               1045                 :                :  *  The proc_number field is used to compare the arguments.
                               1046                 :                :  * ----------
                               1047                 :                :  */
                               1048                 :                : static int
  563 tgl@sss.pgh.pa.us        1049                 :            127 : cmp_lbestatus(const void *a, const void *b)
                               1050                 :                : {
                               1051                 :            127 :     const LocalPgBackendStatus *lbestatus1 = (const LocalPgBackendStatus *) a;
                               1052                 :            127 :     const LocalPgBackendStatus *lbestatus2 = (const LocalPgBackendStatus *) b;
                               1053                 :                : 
   42 heikki.linnakangas@i     1054                 :GNC         127 :     return lbestatus1->proc_number - lbestatus2->proc_number;
                               1055                 :                : }
                               1056                 :                : 
                               1057                 :                : /* ----------
                               1058                 :                :  * pgstat_get_beentry_by_proc_number() -
                               1059                 :                :  *
                               1060                 :                :  *  Support function for the SQL-callable pgstat* functions. Returns
                               1061                 :                :  *  our local copy of the current-activity entry for one backend,
                               1062                 :                :  *  or NULL if the given beid doesn't identify any known session.
                               1063                 :                :  *
                               1064                 :                :  *  The argument is the ProcNumber of the desired session
                               1065                 :                :  *  (note that this is unlike pgstat_get_local_beentry_by_index()).
                               1066                 :                :  *
                               1067                 :                :  *  NB: caller is responsible for a check if the user is permitted to see
                               1068                 :                :  *  this info (especially the querystring).
                               1069                 :                :  * ----------
                               1070                 :                :  */
                               1071                 :                : PgBackendStatus *
                               1072                 :             40 : pgstat_get_beentry_by_proc_number(ProcNumber procNumber)
                               1073                 :                : {
                               1074                 :             40 :     LocalPgBackendStatus *ret = pgstat_get_local_beentry_by_proc_number(procNumber);
                               1075                 :                : 
  228 nathan@postgresql.or     1076         [ +  - ]:CBC          40 :     if (ret)
                               1077                 :             40 :         return &ret->backendStatus;
                               1078                 :                : 
  228 nathan@postgresql.or     1079                 :UBC           0 :     return NULL;
                               1080                 :                : }
                               1081                 :                : 
                               1082                 :                : 
                               1083                 :                : /* ----------
                               1084                 :                :  * pgstat_get_local_beentry_by_proc_number() -
                               1085                 :                :  *
                               1086                 :                :  *  Like pgstat_get_beentry_by_proc_number() but with locally computed additions
                               1087                 :                :  *  (like xid and xmin values of the backend)
                               1088                 :                :  *
                               1089                 :                :  *  The argument is the ProcNumber of the desired session
                               1090                 :                :  *  (note that this is unlike pgstat_get_local_beentry_by_index()).
                               1091                 :                :  *
                               1092                 :                :  *  NB: caller is responsible for checking if the user is permitted to see this
                               1093                 :                :  *  info (especially the querystring).
                               1094                 :                :  * ----------
                               1095                 :                :  */
                               1096                 :                : LocalPgBackendStatus *
   42 heikki.linnakangas@i     1097                 :GNC          40 : pgstat_get_local_beentry_by_proc_number(ProcNumber procNumber)
                               1098                 :                : {
                               1099                 :                :     LocalPgBackendStatus key;
                               1100                 :                : 
 1107 andres@anarazel.de       1101                 :CBC          40 :     pgstat_read_current_status();
                               1102                 :                : 
                               1103                 :                :     /*
                               1104                 :                :      * Since the localBackendStatusTable is in order by proc_number, we can
                               1105                 :                :      * use bsearch() to search it efficiently.
                               1106                 :                :      */
   42 heikki.linnakangas@i     1107                 :GNC          40 :     key.proc_number = procNumber;
  228 nathan@postgresql.or     1108                 :CBC          40 :     return bsearch(&key, localBackendStatusTable, localNumBackends,
                               1109                 :                :                    sizeof(LocalPgBackendStatus), cmp_lbestatus);
                               1110                 :                : }
                               1111                 :                : 
                               1112                 :                : 
                               1113                 :                : /* ----------
                               1114                 :                :  * pgstat_get_local_beentry_by_index() -
                               1115                 :                :  *
                               1116                 :                :  *  Like pgstat_get_beentry_by_proc_number() but with locally computed
                               1117                 :                :  *  additions (like xid and xmin values of the backend)
                               1118                 :                :  *
                               1119                 :                :  *  The idx argument is a 1-based index in the localBackendStatusTable
                               1120                 :                :  *  (note that this is unlike pgstat_get_beentry_by_proc_number()).
                               1121                 :                :  *  Returns NULL if the argument is out of range (no current caller does that).
                               1122                 :                :  *
                               1123                 :                :  *  NB: caller is responsible for a check if the user is permitted to see
                               1124                 :                :  *  this info (especially the querystring).
                               1125                 :                :  * ----------
                               1126                 :                :  */
                               1127                 :                : LocalPgBackendStatus *
                               1128                 :           8839 : pgstat_get_local_beentry_by_index(int idx)
                               1129                 :                : {
 1107 andres@anarazel.de       1130                 :           8839 :     pgstat_read_current_status();
                               1131                 :                : 
  228 nathan@postgresql.or     1132   [ +  -  -  + ]:           8839 :     if (idx < 1 || idx > localNumBackends)
 1107 andres@anarazel.de       1133                 :UBC           0 :         return NULL;
                               1134                 :                : 
  228 nathan@postgresql.or     1135                 :CBC        8839 :     return &localBackendStatusTable[idx - 1];
                               1136                 :                : }
                               1137                 :                : 
                               1138                 :                : 
                               1139                 :                : /* ----------
                               1140                 :                :  * pgstat_fetch_stat_numbackends() -
                               1141                 :                :  *
                               1142                 :                :  *  Support function for the SQL-callable pgstat* functions. Returns
                               1143                 :                :  *  the number of sessions known in the localBackendStatusTable, i.e.
                               1144                 :                :  *  the maximum 1-based index to pass to pgstat_get_local_beentry_by_index().
                               1145                 :                :  * ----------
                               1146                 :                :  */
                               1147                 :                : int
 1107 andres@anarazel.de       1148                 :           1340 : pgstat_fetch_stat_numbackends(void)
                               1149                 :                : {
                               1150                 :           1340 :     pgstat_read_current_status();
                               1151                 :                : 
                               1152                 :           1340 :     return localNumBackends;
                               1153                 :                : }
                               1154                 :                : 
                               1155                 :                : /*
                               1156                 :                :  * Convert a potentially unsafely truncated activity string (see
                               1157                 :                :  * PgBackendStatus.st_activity_raw's documentation) into a correctly truncated
                               1158                 :                :  * one.
                               1159                 :                :  *
                               1160                 :                :  * The returned string is allocated in the caller's memory context and may be
                               1161                 :                :  * freed.
                               1162                 :                :  */
                               1163                 :                : char *
                               1164                 :           6040 : pgstat_clip_activity(const char *raw_activity)
                               1165                 :                : {
                               1166                 :                :     char       *activity;
                               1167                 :                :     int         rawlen;
                               1168                 :                :     int         cliplen;
                               1169                 :                : 
                               1170                 :                :     /*
                               1171                 :                :      * Some callers, like pgstat_get_backend_current_activity(), do not
                               1172                 :                :      * guarantee that the buffer isn't concurrently modified. We try to take
                               1173                 :                :      * care that the buffer is always terminated by a NUL byte regardless, but
                               1174                 :                :      * let's still be paranoid about the string's length. In those cases the
                               1175                 :                :      * underlying buffer is guaranteed to be pgstat_track_activity_query_size
                               1176                 :                :      * large.
                               1177                 :                :      */
                               1178                 :           6040 :     activity = pnstrdup(raw_activity, pgstat_track_activity_query_size - 1);
                               1179                 :                : 
                               1180                 :                :     /* now double-guaranteed to be NUL terminated */
                               1181                 :           6040 :     rawlen = strlen(activity);
                               1182                 :                : 
                               1183                 :                :     /*
                               1184                 :                :      * All supported server-encodings make it possible to determine the length
                               1185                 :                :      * of a multi-byte character from its first byte (this is not the case for
                               1186                 :                :      * client encodings, see GB18030). As st_activity is always stored using
                               1187                 :                :      * server encoding, this allows us to perform multi-byte aware truncation,
                               1188                 :                :      * even if the string earlier was truncated in the middle of a multi-byte
                               1189                 :                :      * character.
                               1190                 :                :      */
                               1191                 :           6040 :     cliplen = pg_mbcliplen(activity, rawlen,
                               1192                 :                :                            pgstat_track_activity_query_size - 1);
                               1193                 :                : 
                               1194                 :           6040 :     activity[cliplen] = '\0';
                               1195                 :                : 
                               1196                 :           6040 :     return activity;
                               1197                 :                : }
        

Generated by: LCOV version 2.1-beta2-3-g6141622