LCOV - differential code coverage report
Current view: top level - src/backend/utils/activity - backend_status.c (source / functions) Coverage Total Hit UNC UBC GBC GIC GNC CBC ECB DUB DCB
Current: bed3ffbf9d952be6c7d739d068cdce44c046dfb7 vs 574581b50ac9c63dd9e4abebb731a3b67e5b50f6 Lines: 95.5 % 352 336 4 12 1 22 313 1 60
Current Date: 2026-05-05 10:23:31 +0900 Functions: 96.2 % 26 25 1 3 22 3
Baseline: lcov-20260505-025707-baseline Branches: 71.4 % 210 150 60 1 6 143 40 38
Baseline Date: 2026-05-05 10:27:06 +0900 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(7,30] days: 84.6 % 26 22 4 22
(30,360] days: 100.0 % 9 9 9
(360..) days: 96.2 % 317 305 12 1 304 1
Function coverage date bins:
(7,30] days: 66.7 % 3 2 1 2
(30,360] days: 100.0 % 2 2 2
(360..) days: 100.0 % 21 21 1 20
Branch coverage date bins:
(7,30] days: 100.0 % 6 6 6
(30,360] days: 100.0 % 4 4 4
(360..) days: 70.0 % 200 140 60 1 139

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

Generated by: LCOV version 2.5.0-beta