LCOV - differential code coverage report
Current view: top level - src/backend/utils/activity - backend_status.c (source / functions) Coverage Total Hit LBC UBC CBC
Current: c70b6db34ffeab48beef1fb4ce61bcad3772b8dd vs 06473f5a344df8c9594ead90a609b86f6724cff8 Lines: 96.4 % 386 372 2 12 372
Current Date: 2025-09-06 07:49:51 +0900 Functions: 100.0 % 26 26 26
Baseline: lcov-20250906-005545-baseline Branches: 63.5 % 282 179 2 101 179
Baseline Date: 2025-09-05 08:21:35 +0100 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(30,360] days: 97.6 % 84 82 2 82
(360..) days: 96.0 % 302 290 2 10 290
Function coverage date bins:
(30,360] days: 100.0 % 7 7 7
(360..) days: 100.0 % 19 19 19
Branch coverage date bins:
(30,360] days: 69.6 % 46 32 14 32
(360..) days: 62.3 % 236 147 2 87 147

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

Generated by: LCOV version 2.4-beta