From: Kyotaro Horiguchi Date: Thu, 8 Nov 2018 18:43:55 +0900 Subject: [PATCH 8/8] Split out backend status monitor part from pgstat A large file, pgstat.c, contained two major facilities, backend status monitor and database usage monitor. Split out the former part from the file and name the module "bestatus". --- src/backend/Makefile | 2 +- src/backend/access/heap/rewriteheap.c | 20 +- src/backend/access/nbtree/nbtree.c | 2 +- src/backend/access/nbtree/nbtsort.c | 4 +- src/backend/access/transam/clog.c | 6 +- src/backend/access/transam/parallel.c | 2 +- src/backend/access/transam/slru.c | 24 +- src/backend/access/transam/timeline.c | 22 +- src/backend/access/transam/twophase.c | 17 +- src/backend/access/transam/xact.c | 17 +- src/backend/access/transam/xlog.c | 67 +- src/backend/access/transam/xlogfuncs.c | 2 +- src/backend/access/transam/xlogutils.c | 6 +- src/backend/bootstrap/bootstrap.c | 22 +- src/backend/commands/vacuumlazy.c | 37 +- src/backend/executor/execParallel.c | 4 +- src/backend/executor/nodeBitmapHeapscan.c | 1 + src/backend/executor/nodeGather.c | 2 +- src/backend/executor/nodeHash.c | 2 +- src/backend/executor/nodeHashjoin.c | 2 +- src/backend/libpq/be-secure-openssl.c | 2 +- src/backend/libpq/be-secure.c | 2 +- src/backend/libpq/pqmq.c | 2 +- src/backend/postmaster/Makefile | 2 +- src/backend/postmaster/autovacuum.c | 11 +- src/backend/postmaster/bgworker.c | 2 +- src/backend/postmaster/bgwriter.c | 3 +- src/backend/postmaster/checkpointer.c | 3 +- src/backend/postmaster/pgarch.c | 1 + src/backend/postmaster/postmaster.c | 5 +- src/backend/postmaster/syslogger.c | 2 +- src/backend/postmaster/walwriter.c | 4 +- src/backend/replication/basebackup.c | 2 +- .../libpqwalreceiver/libpqwalreceiver.c | 2 +- src/backend/replication/logical/launcher.c | 2 +- src/backend/replication/logical/origin.c | 3 +- src/backend/replication/logical/reorderbuffer.c | 18 +- src/backend/replication/logical/snapbuild.c | 26 +- src/backend/replication/logical/tablesync.c | 6 +- src/backend/replication/logical/worker.c | 17 +- src/backend/replication/slot.c | 26 +- src/backend/replication/syncrep.c | 2 +- src/backend/replication/walreceiver.c | 2 +- src/backend/replication/walsender.c | 18 +- src/backend/statmon/Makefile | 17 + src/backend/statmon/bestatus.c | 1759 ++++++++++++++++++++ src/backend/{postmaster => statmon}/pgstat.c | 1717 +------------------ src/backend/storage/buffer/bufmgr.c | 1 + src/backend/storage/file/buffile.c | 2 +- src/backend/storage/file/copydir.c | 12 +- src/backend/storage/file/fd.c | 25 +- src/backend/storage/ipc/dsm_impl.c | 6 +- src/backend/storage/ipc/latch.c | 6 +- src/backend/storage/ipc/procarray.c | 6 +- src/backend/storage/ipc/shm_mq.c | 2 +- src/backend/storage/ipc/standby.c | 2 +- src/backend/storage/lmgr/deadlock.c | 3 +- src/backend/storage/lmgr/lwlock.c | 6 +- src/backend/storage/lmgr/predicate.c | 2 +- src/backend/storage/lmgr/proc.c | 2 +- src/backend/storage/smgr/md.c | 2 +- src/backend/tcop/postgres.c | 17 +- src/backend/utils/adt/misc.c | 2 +- src/backend/utils/adt/pgstatfuncs.c | 61 +- src/backend/utils/cache/relmapper.c | 14 +- src/backend/utils/init/miscinit.c | 32 +- src/backend/utils/init/postinit.c | 12 +- src/backend/utils/misc/guc.c | 7 +- src/include/bestatus.h | 545 ++++++ src/include/pgstat.h | 514 +----- 70 files changed, 2691 insertions(+), 2507 deletions(-) create mode 100644 src/backend/statmon/Makefile create mode 100644 src/backend/statmon/bestatus.c rename src/backend/{postmaster => statmon}/pgstat.c (70%) create mode 100644 src/include/bestatus.h diff --git a/src/backend/Makefile b/src/backend/Makefile index 3a58bf6685..9921dca7f9 100644 --- a/src/backend/Makefile +++ b/src/backend/Makefile @@ -20,7 +20,7 @@ include $(top_builddir)/src/Makefile.global SUBDIRS = access bootstrap catalog parser commands executor foreign lib libpq \ main nodes optimizer partitioning port postmaster \ regex replication rewrite \ - statistics storage tcop tsearch utils $(top_builddir)/src/timezone \ + statistics statmon storage tcop tsearch utils $(top_builddir)/src/timezone \ jit include $(srcdir)/common.mk diff --git a/src/backend/access/heap/rewriteheap.c b/src/backend/access/heap/rewriteheap.c index 7127788964..4a7c284d81 100644 --- a/src/backend/access/heap/rewriteheap.c +++ b/src/backend/access/heap/rewriteheap.c @@ -115,12 +115,12 @@ #include "access/xact.h" #include "access/xloginsert.h" +#include "bestatus.h" + #include "catalog/catalog.h" #include "lib/ilist.h" -#include "pgstat.h" - #include "replication/logical.h" #include "replication/slot.h" @@ -1159,13 +1159,13 @@ heap_xlog_logical_rewrite(XLogReaderState *r) * Truncate all data that's not guaranteed to have been safely fsynced (by * previous record or by the last checkpoint). */ - pgstat_report_wait_start(WAIT_EVENT_LOGICAL_REWRITE_TRUNCATE); + bestatus_report_wait_start(WAIT_EVENT_LOGICAL_REWRITE_TRUNCATE); if (ftruncate(fd, xlrec->offset) != 0) ereport(ERROR, (errcode_for_file_access(), errmsg("could not truncate file \"%s\" to %u: %m", path, (uint32) xlrec->offset))); - pgstat_report_wait_end(); + bestatus_report_wait_end(); /* now seek to the position we want to write our data to */ if (lseek(fd, xlrec->offset, SEEK_SET) != xlrec->offset) @@ -1180,7 +1180,7 @@ heap_xlog_logical_rewrite(XLogReaderState *r) /* write out tail end of mapping file (again) */ errno = 0; - pgstat_report_wait_start(WAIT_EVENT_LOGICAL_REWRITE_MAPPING_WRITE); + bestatus_report_wait_start(WAIT_EVENT_LOGICAL_REWRITE_MAPPING_WRITE); if (write(fd, data, len) != len) { /* if write didn't set errno, assume problem is no disk space */ @@ -1190,19 +1190,19 @@ heap_xlog_logical_rewrite(XLogReaderState *r) (errcode_for_file_access(), errmsg("could not write to file \"%s\": %m", path))); } - pgstat_report_wait_end(); + bestatus_report_wait_end(); /* * Now fsync all previously written data. We could improve things and only * do this for the last write to a file, but the required bookkeeping * doesn't seem worth the trouble. */ - pgstat_report_wait_start(WAIT_EVENT_LOGICAL_REWRITE_MAPPING_SYNC); + bestatus_report_wait_start(WAIT_EVENT_LOGICAL_REWRITE_MAPPING_SYNC); if (pg_fsync(fd) != 0) ereport(ERROR, (errcode_for_file_access(), errmsg("could not fsync file \"%s\": %m", path))); - pgstat_report_wait_end(); + bestatus_report_wait_end(); CloseTransientFile(fd); } @@ -1296,12 +1296,12 @@ CheckPointLogicalRewriteHeap(void) * changed or have only been created since the checkpoint's start, * but it's currently not deemed worth the effort. */ - pgstat_report_wait_start(WAIT_EVENT_LOGICAL_REWRITE_CHECKPOINT_SYNC); + bestatus_report_wait_start(WAIT_EVENT_LOGICAL_REWRITE_CHECKPOINT_SYNC); if (pg_fsync(fd) != 0) ereport(ERROR, (errcode_for_file_access(), errmsg("could not fsync file \"%s\": %m", path))); - pgstat_report_wait_end(); + bestatus_report_wait_end(); CloseTransientFile(fd); } } diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c index e8725fbbe1..6679dbc3a5 100644 --- a/src/backend/access/nbtree/nbtree.c +++ b/src/backend/access/nbtree/nbtree.c @@ -22,10 +22,10 @@ #include "access/nbtxlog.h" #include "access/relscan.h" #include "access/xlog.h" +#include "bestatus.h" #include "commands/vacuum.h" #include "miscadmin.h" #include "nodes/execnodes.h" -#include "pgstat.h" #include "postmaster/autovacuum.h" #include "storage/condition_variable.h" #include "storage/indexfsm.h" diff --git a/src/backend/access/nbtree/nbtsort.c b/src/backend/access/nbtree/nbtsort.c index 16f5755777..6f4fd371c8 100644 --- a/src/backend/access/nbtree/nbtsort.c +++ b/src/backend/access/nbtree/nbtsort.c @@ -63,9 +63,9 @@ #include "access/xact.h" #include "access/xlog.h" #include "access/xloginsert.h" +#include "bestatus.h" #include "catalog/index.h" #include "miscadmin.h" -#include "pgstat.h" #include "storage/smgr.h" #include "tcop/tcopprot.h" /* pgrminclude ignore */ #include "utils/rel.h" @@ -1538,7 +1538,7 @@ _bt_parallel_build_main(dsm_segment *seg, shm_toc *toc) debug_query_string = sharedquery; /* Report the query string from leader */ - pgstat_report_activity(STATE_RUNNING, debug_query_string); + bestatus_report_activity(STATE_RUNNING, debug_query_string); /* Look up nbtree shared state */ btshared = shm_toc_lookup(toc, PARALLEL_KEY_BTREE_SHARED, false); diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 8b7ff5b0c2..85e364b117 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -38,8 +38,8 @@ #include "access/xlog.h" #include "access/xloginsert.h" #include "access/xlogutils.h" +#include "bestatus.h" #include "miscadmin.h" -#include "pgstat.h" #include "pg_trace.h" #include "storage/proc.h" @@ -480,7 +480,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, int extraWaits = 0; /* Sleep until the leader updates our XID status. */ - pgstat_report_wait_start(WAIT_EVENT_CLOG_GROUP_UPDATE); + bestatus_report_wait_start(WAIT_EVENT_CLOG_GROUP_UPDATE); for (;;) { /* acts as a read barrier */ @@ -489,7 +489,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, break; extraWaits++; } - pgstat_report_wait_end(); + bestatus_report_wait_end(); Assert(pg_atomic_read_u32(&proc->clogGroupNext) == INVALID_PGPROCNO); diff --git a/src/backend/access/transam/parallel.c b/src/backend/access/transam/parallel.c index 84197192ec..7e5c84bd5f 100644 --- a/src/backend/access/transam/parallel.c +++ b/src/backend/access/transam/parallel.c @@ -19,6 +19,7 @@ #include "access/session.h" #include "access/xact.h" #include "access/xlog.h" +#include "bestatus.h" #include "catalog/pg_enum.h" #include "catalog/index.h" #include "catalog/namespace.h" @@ -29,7 +30,6 @@ #include "libpq/pqmq.h" #include "miscadmin.h" #include "optimizer/planmain.h" -#include "pgstat.h" #include "storage/ipc.h" #include "storage/sinval.h" #include "storage/spin.h" diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c index 1132eef038..d564cf8ff3 100644 --- a/src/backend/access/transam/slru.c +++ b/src/backend/access/transam/slru.c @@ -54,7 +54,7 @@ #include "access/slru.h" #include "access/transam.h" #include "access/xlog.h" -#include "pgstat.h" +#include "bestatus.h" #include "storage/fd.h" #include "storage/shmem.h" #include "miscadmin.h" @@ -680,16 +680,16 @@ SlruPhysicalReadPage(SlruCtl ctl, int pageno, int slotno) } errno = 0; - pgstat_report_wait_start(WAIT_EVENT_SLRU_READ); + bestatus_report_wait_start(WAIT_EVENT_SLRU_READ); if (read(fd, shared->page_buffer[slotno], BLCKSZ) != BLCKSZ) { - pgstat_report_wait_end(); + bestatus_report_wait_end(); slru_errcause = SLRU_READ_FAILED; slru_errno = errno; CloseTransientFile(fd); return false; } - pgstat_report_wait_end(); + bestatus_report_wait_end(); if (CloseTransientFile(fd)) { @@ -841,10 +841,10 @@ SlruPhysicalWritePage(SlruCtl ctl, int pageno, int slotno, SlruFlush fdata) } errno = 0; - pgstat_report_wait_start(WAIT_EVENT_SLRU_WRITE); + bestatus_report_wait_start(WAIT_EVENT_SLRU_WRITE); if (write(fd, shared->page_buffer[slotno], BLCKSZ) != BLCKSZ) { - pgstat_report_wait_end(); + bestatus_report_wait_end(); /* if write didn't set errno, assume problem is no disk space */ if (errno == 0) errno = ENOSPC; @@ -854,7 +854,7 @@ SlruPhysicalWritePage(SlruCtl ctl, int pageno, int slotno, SlruFlush fdata) CloseTransientFile(fd); return false; } - pgstat_report_wait_end(); + bestatus_report_wait_end(); /* * If not part of Flush, need to fsync now. We assume this happens @@ -862,16 +862,16 @@ SlruPhysicalWritePage(SlruCtl ctl, int pageno, int slotno, SlruFlush fdata) */ if (!fdata) { - pgstat_report_wait_start(WAIT_EVENT_SLRU_SYNC); + bestatus_report_wait_start(WAIT_EVENT_SLRU_SYNC); if (ctl->do_fsync && pg_fsync(fd)) { - pgstat_report_wait_end(); + bestatus_report_wait_end(); slru_errcause = SLRU_FSYNC_FAILED; slru_errno = errno; CloseTransientFile(fd); return false; } - pgstat_report_wait_end(); + bestatus_report_wait_end(); if (CloseTransientFile(fd)) { @@ -1139,7 +1139,7 @@ SimpleLruFlush(SlruCtl ctl, bool allow_redirtied) ok = true; for (i = 0; i < fdata.num_files; i++) { - pgstat_report_wait_start(WAIT_EVENT_SLRU_FLUSH_SYNC); + bestatus_report_wait_start(WAIT_EVENT_SLRU_FLUSH_SYNC); if (ctl->do_fsync && pg_fsync(fdata.fd[i])) { slru_errcause = SLRU_FSYNC_FAILED; @@ -1147,7 +1147,7 @@ SimpleLruFlush(SlruCtl ctl, bool allow_redirtied) pageno = fdata.segno[i] * SLRU_PAGES_PER_SEGMENT; ok = false; } - pgstat_report_wait_end(); + bestatus_report_wait_end(); if (CloseTransientFile(fdata.fd[i])) { diff --git a/src/backend/access/transam/timeline.c b/src/backend/access/transam/timeline.c index 61d36050c3..626eb0ead2 100644 --- a/src/backend/access/transam/timeline.c +++ b/src/backend/access/transam/timeline.c @@ -38,7 +38,7 @@ #include "access/xlog.h" #include "access/xlog_internal.h" #include "access/xlogdefs.h" -#include "pgstat.h" +#include "bestatus.h" #include "storage/fd.h" /* @@ -338,9 +338,9 @@ writeTimeLineHistory(TimeLineID newTLI, TimeLineID parentTLI, for (;;) { errno = 0; - pgstat_report_wait_start(WAIT_EVENT_TIMELINE_HISTORY_READ); + bestatus_report_wait_start(WAIT_EVENT_TIMELINE_HISTORY_READ); nbytes = (int) read(srcfd, buffer, sizeof(buffer)); - pgstat_report_wait_end(); + bestatus_report_wait_end(); if (nbytes < 0 || errno != 0) ereport(ERROR, (errcode_for_file_access(), @@ -348,7 +348,7 @@ writeTimeLineHistory(TimeLineID newTLI, TimeLineID parentTLI, if (nbytes == 0) break; errno = 0; - pgstat_report_wait_start(WAIT_EVENT_TIMELINE_HISTORY_WRITE); + bestatus_report_wait_start(WAIT_EVENT_TIMELINE_HISTORY_WRITE); if ((int) write(fd, buffer, nbytes) != nbytes) { int save_errno = errno; @@ -368,7 +368,7 @@ writeTimeLineHistory(TimeLineID newTLI, TimeLineID parentTLI, (errcode_for_file_access(), errmsg("could not write to file \"%s\": %m", tmppath))); } - pgstat_report_wait_end(); + bestatus_report_wait_end(); } CloseTransientFile(srcfd); } @@ -404,12 +404,12 @@ writeTimeLineHistory(TimeLineID newTLI, TimeLineID parentTLI, errmsg("could not write to file \"%s\": %m", tmppath))); } - pgstat_report_wait_start(WAIT_EVENT_TIMELINE_HISTORY_SYNC); + bestatus_report_wait_start(WAIT_EVENT_TIMELINE_HISTORY_SYNC); if (pg_fsync(fd) != 0) ereport(ERROR, (errcode_for_file_access(), errmsg("could not fsync file \"%s\": %m", tmppath))); - pgstat_report_wait_end(); + bestatus_report_wait_end(); if (CloseTransientFile(fd)) ereport(ERROR, @@ -465,7 +465,7 @@ writeTimeLineHistoryFile(TimeLineID tli, char *content, int size) errmsg("could not create file \"%s\": %m", tmppath))); errno = 0; - pgstat_report_wait_start(WAIT_EVENT_TIMELINE_HISTORY_FILE_WRITE); + bestatus_report_wait_start(WAIT_EVENT_TIMELINE_HISTORY_FILE_WRITE); if ((int) write(fd, content, size) != size) { int save_errno = errno; @@ -481,14 +481,14 @@ writeTimeLineHistoryFile(TimeLineID tli, char *content, int size) (errcode_for_file_access(), errmsg("could not write to file \"%s\": %m", tmppath))); } - pgstat_report_wait_end(); + bestatus_report_wait_end(); - pgstat_report_wait_start(WAIT_EVENT_TIMELINE_HISTORY_FILE_SYNC); + bestatus_report_wait_start(WAIT_EVENT_TIMELINE_HISTORY_FILE_SYNC); if (pg_fsync(fd) != 0) ereport(ERROR, (errcode_for_file_access(), errmsg("could not fsync file \"%s\": %m", tmppath))); - pgstat_report_wait_end(); + bestatus_report_wait_end(); if (CloseTransientFile(fd)) ereport(ERROR, diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c index 3942734e5a..eaf0c5ac64 100644 --- a/src/backend/access/transam/twophase.c +++ b/src/backend/access/transam/twophase.c @@ -87,6 +87,7 @@ #include "access/xloginsert.h" #include "access/xlogutils.h" #include "access/xlogreader.h" +#include "bestatus.h" #include "catalog/pg_type.h" #include "catalog/storage.h" #include "funcapi.h" @@ -1271,7 +1272,7 @@ ReadTwoPhaseFile(TransactionId xid, bool missing_ok) */ buf = (char *) palloc(stat.st_size); - pgstat_report_wait_start(WAIT_EVENT_TWOPHASE_FILE_READ); + bestatus_report_wait_start(WAIT_EVENT_TWOPHASE_FILE_READ); r = read(fd, buf, stat.st_size); if (r != stat.st_size) { @@ -1285,7 +1286,7 @@ ReadTwoPhaseFile(TransactionId xid, bool missing_ok) path, r, (Size) stat.st_size))); } - pgstat_report_wait_end(); + bestatus_report_wait_end(); CloseTransientFile(fd); hdr = (TwoPhaseFileHeader *) buf; @@ -1660,12 +1661,12 @@ RecreateTwoPhaseFile(TransactionId xid, void *content, int len) /* Write content and CRC */ errno = 0; - pgstat_report_wait_start(WAIT_EVENT_TWOPHASE_FILE_WRITE); + bestatus_report_wait_start(WAIT_EVENT_TWOPHASE_FILE_WRITE); if (write(fd, content, len) != len) { int save_errno = errno; - pgstat_report_wait_end(); + bestatus_report_wait_end(); CloseTransientFile(fd); /* if write didn't set errno, assume problem is no disk space */ @@ -1678,7 +1679,7 @@ RecreateTwoPhaseFile(TransactionId xid, void *content, int len) { int save_errno = errno; - pgstat_report_wait_end(); + bestatus_report_wait_end(); CloseTransientFile(fd); /* if write didn't set errno, assume problem is no disk space */ @@ -1687,13 +1688,13 @@ RecreateTwoPhaseFile(TransactionId xid, void *content, int len) (errcode_for_file_access(), errmsg("could not write file \"%s\": %m", path))); } - pgstat_report_wait_end(); + bestatus_report_wait_end(); /* * We must fsync the file because the end-of-replay checkpoint will not do * so, there being no GXACT in shared memory yet to tell it to. */ - pgstat_report_wait_start(WAIT_EVENT_TWOPHASE_FILE_SYNC); + bestatus_report_wait_start(WAIT_EVENT_TWOPHASE_FILE_SYNC); if (pg_fsync(fd) != 0) { int save_errno = errno; @@ -1704,7 +1705,7 @@ RecreateTwoPhaseFile(TransactionId xid, void *content, int len) (errcode_for_file_access(), errmsg("could not fsync file \"%s\": %m", path))); } - pgstat_report_wait_end(); + bestatus_report_wait_end(); if (CloseTransientFile(fd) != 0) ereport(ERROR, diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c index 8c1621d949..a0f9dd0b2e 100644 --- a/src/backend/access/transam/xact.c +++ b/src/backend/access/transam/xact.c @@ -30,6 +30,7 @@ #include "access/xlog.h" #include "access/xloginsert.h" #include "access/xlogutils.h" +#include "bestatus.h" #include "catalog/namespace.h" #include "catalog/pg_enum.h" #include "catalog/storage.h" @@ -1905,7 +1906,7 @@ StartTransaction(void) } else Assert(xactStartTimestamp != 0); - pgstat_report_xact_timestamp(xactStartTimestamp); + bestatus_report_xact_timestamp(xactStartTimestamp); /* Mark xactStopTimestamp as unset. */ xactStopTimestamp = 0; @@ -2146,7 +2147,7 @@ CommitTransaction(void) AtEOXact_PgStat(true); AtEOXact_Snapshot(true, false); AtEOXact_ApplyLauncher(true); - pgstat_report_xact_timestamp(0); + bestatus_report_xact_timestamp(0); CurrentResourceOwner = NULL; ResourceOwnerDelete(TopTransactionResourceOwner); @@ -2424,7 +2425,7 @@ PrepareTransaction(void) AtEOXact_HashTables(true); /* don't call AtEOXact_PgStat here; we fixed pgstat state above */ AtEOXact_Snapshot(true, true); - pgstat_report_xact_timestamp(0); + bestatus_report_xact_timestamp(0); CurrentResourceOwner = NULL; ResourceOwnerDelete(TopTransactionResourceOwner); @@ -2481,8 +2482,8 @@ AbortTransaction(void) LWLockReleaseAll(); /* Clear wait information and command progress indicator */ - pgstat_report_wait_end(); - pgstat_progress_end_command(); + bestatus_report_wait_end(); + bestatus_progress_end_command(); /* Clean up buffer I/O and buffer context locks, too */ AbortBufferIO(); @@ -2627,7 +2628,7 @@ AbortTransaction(void) AtEOXact_HashTables(false); AtEOXact_PgStat(false); AtEOXact_ApplyLauncher(false); - pgstat_report_xact_timestamp(0); + bestatus_report_xact_timestamp(0); } /* @@ -4703,8 +4704,8 @@ AbortSubTransaction(void) */ LWLockReleaseAll(); - pgstat_report_wait_end(); - pgstat_progress_end_command(); + bestatus_report_wait_end(); + bestatus_progress_end_command(); AbortBufferIO(); UnlockBuffers(); diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index e72040178a..b5289197fa 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -36,6 +36,7 @@ #include "access/xloginsert.h" #include "access/xlogreader.h" #include "access/xlogutils.h" +#include "bestatus.h" #include "catalog/catversion.h" #include "catalog/pg_control.h" #include "catalog/pg_database.h" @@ -2497,9 +2498,9 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible) do { errno = 0; - pgstat_report_wait_start(WAIT_EVENT_WAL_WRITE); + bestatus_report_wait_start(WAIT_EVENT_WAL_WRITE); written = write(openLogFile, from, nleft); - pgstat_report_wait_end(); + bestatus_report_wait_end(); if (written <= 0) { if (errno == EINTR) @@ -3268,7 +3269,7 @@ XLogFileInit(XLogSegNo logsegno, bool *use_existent, bool use_lock) for (nbytes = 0; nbytes < wal_segment_size; nbytes += XLOG_BLCKSZ) { errno = 0; - pgstat_report_wait_start(WAIT_EVENT_WAL_INIT_WRITE); + bestatus_report_wait_start(WAIT_EVENT_WAL_INIT_WRITE); if ((int) write(fd, zbuffer.data, XLOG_BLCKSZ) != (int) XLOG_BLCKSZ) { int save_errno = errno; @@ -3287,10 +3288,10 @@ XLogFileInit(XLogSegNo logsegno, bool *use_existent, bool use_lock) (errcode_for_file_access(), errmsg("could not write to file \"%s\": %m", tmppath))); } - pgstat_report_wait_end(); + bestatus_report_wait_end(); } - pgstat_report_wait_start(WAIT_EVENT_WAL_INIT_SYNC); + bestatus_report_wait_start(WAIT_EVENT_WAL_INIT_SYNC); if (pg_fsync(fd) != 0) { int save_errno = errno; @@ -3301,7 +3302,7 @@ XLogFileInit(XLogSegNo logsegno, bool *use_existent, bool use_lock) (errcode_for_file_access(), errmsg("could not fsync file \"%s\": %m", tmppath))); } - pgstat_report_wait_end(); + bestatus_report_wait_end(); if (close(fd)) ereport(ERROR, @@ -3427,7 +3428,7 @@ XLogFileCopy(XLogSegNo destsegno, TimeLineID srcTLI, XLogSegNo srcsegno, if (nread > sizeof(buffer)) nread = sizeof(buffer); - pgstat_report_wait_start(WAIT_EVENT_WAL_COPY_READ); + bestatus_report_wait_start(WAIT_EVENT_WAL_COPY_READ); r = read(srcfd, buffer.data, nread); if (r != nread) { @@ -3442,10 +3443,10 @@ XLogFileCopy(XLogSegNo destsegno, TimeLineID srcTLI, XLogSegNo srcsegno, errmsg("could not read file \"%s\": read %d of %zu", path, r, (Size) nread))); } - pgstat_report_wait_end(); + bestatus_report_wait_end(); } errno = 0; - pgstat_report_wait_start(WAIT_EVENT_WAL_COPY_WRITE); + bestatus_report_wait_start(WAIT_EVENT_WAL_COPY_WRITE); if ((int) write(fd, buffer.data, sizeof(buffer)) != (int) sizeof(buffer)) { int save_errno = errno; @@ -3461,15 +3462,15 @@ XLogFileCopy(XLogSegNo destsegno, TimeLineID srcTLI, XLogSegNo srcsegno, (errcode_for_file_access(), errmsg("could not write to file \"%s\": %m", tmppath))); } - pgstat_report_wait_end(); + bestatus_report_wait_end(); } - pgstat_report_wait_start(WAIT_EVENT_WAL_COPY_SYNC); + bestatus_report_wait_start(WAIT_EVENT_WAL_COPY_SYNC); if (pg_fsync(fd) != 0) ereport(ERROR, (errcode_for_file_access(), errmsg("could not fsync file \"%s\": %m", tmppath))); - pgstat_report_wait_end(); + bestatus_report_wait_end(); if (CloseTransientFile(fd)) ereport(ERROR, @@ -4521,7 +4522,7 @@ WriteControlFile(void) XLOG_CONTROL_FILE))); errno = 0; - pgstat_report_wait_start(WAIT_EVENT_CONTROL_FILE_WRITE); + bestatus_report_wait_start(WAIT_EVENT_CONTROL_FILE_WRITE); if (write(fd, buffer, PG_CONTROL_FILE_SIZE) != PG_CONTROL_FILE_SIZE) { /* if write didn't set errno, assume problem is no disk space */ @@ -4532,15 +4533,15 @@ WriteControlFile(void) errmsg("could not write to file \"%s\": %m", XLOG_CONTROL_FILE))); } - pgstat_report_wait_end(); + bestatus_report_wait_end(); - pgstat_report_wait_start(WAIT_EVENT_CONTROL_FILE_SYNC); + bestatus_report_wait_start(WAIT_EVENT_CONTROL_FILE_SYNC); if (pg_fsync(fd) != 0) ereport(PANIC, (errcode_for_file_access(), errmsg("could not fsync file \"%s\": %m", XLOG_CONTROL_FILE))); - pgstat_report_wait_end(); + bestatus_report_wait_end(); if (close(fd)) ereport(PANIC, @@ -4568,7 +4569,7 @@ ReadControlFile(void) errmsg("could not open file \"%s\": %m", XLOG_CONTROL_FILE))); - pgstat_report_wait_start(WAIT_EVENT_CONTROL_FILE_READ); + bestatus_report_wait_start(WAIT_EVENT_CONTROL_FILE_READ); r = read(fd, ControlFile, sizeof(ControlFileData)); if (r != sizeof(ControlFileData)) { @@ -4583,7 +4584,7 @@ ReadControlFile(void) errmsg("could not read file \"%s\": read %d of %zu", XLOG_CONTROL_FILE, r, sizeof(ControlFileData)))); } - pgstat_report_wait_end(); + bestatus_report_wait_end(); close(fd); @@ -4780,7 +4781,7 @@ UpdateControlFile(void) errmsg("could not open file \"%s\": %m", XLOG_CONTROL_FILE))); errno = 0; - pgstat_report_wait_start(WAIT_EVENT_CONTROL_FILE_WRITE_UPDATE); + bestatus_report_wait_start(WAIT_EVENT_CONTROL_FILE_WRITE_UPDATE); if (write(fd, ControlFile, sizeof(ControlFileData)) != sizeof(ControlFileData)) { /* if write didn't set errno, assume problem is no disk space */ @@ -4791,15 +4792,15 @@ UpdateControlFile(void) errmsg("could not write to file \"%s\": %m", XLOG_CONTROL_FILE))); } - pgstat_report_wait_end(); + bestatus_report_wait_end(); - pgstat_report_wait_start(WAIT_EVENT_CONTROL_FILE_SYNC_UPDATE); + bestatus_report_wait_start(WAIT_EVENT_CONTROL_FILE_SYNC_UPDATE); if (pg_fsync(fd) != 0) ereport(PANIC, (errcode_for_file_access(), errmsg("could not fsync file \"%s\": %m", XLOG_CONTROL_FILE))); - pgstat_report_wait_end(); + bestatus_report_wait_end(); if (close(fd)) ereport(PANIC, @@ -5219,7 +5220,7 @@ BootStrapXLOG(void) /* Write the first page with the initial record */ errno = 0; - pgstat_report_wait_start(WAIT_EVENT_WAL_BOOTSTRAP_WRITE); + bestatus_report_wait_start(WAIT_EVENT_WAL_BOOTSTRAP_WRITE); if (write(openLogFile, page, XLOG_BLCKSZ) != XLOG_BLCKSZ) { /* if write didn't set errno, assume problem is no disk space */ @@ -5229,14 +5230,14 @@ BootStrapXLOG(void) (errcode_for_file_access(), errmsg("could not write bootstrap write-ahead log file: %m"))); } - pgstat_report_wait_end(); + bestatus_report_wait_end(); - pgstat_report_wait_start(WAIT_EVENT_WAL_BOOTSTRAP_SYNC); + bestatus_report_wait_start(WAIT_EVENT_WAL_BOOTSTRAP_SYNC); if (pg_fsync(openLogFile) != 0) ereport(PANIC, (errcode_for_file_access(), errmsg("could not fsync bootstrap write-ahead log file: %m"))); - pgstat_report_wait_end(); + bestatus_report_wait_end(); if (close(openLogFile)) ereport(PANIC, @@ -10276,13 +10277,13 @@ assign_xlog_sync_method(int new_sync_method, void *extra) */ if (openLogFile >= 0) { - pgstat_report_wait_start(WAIT_EVENT_WAL_SYNC_METHOD_ASSIGN); + bestatus_report_wait_start(WAIT_EVENT_WAL_SYNC_METHOD_ASSIGN); if (pg_fsync(openLogFile) != 0) ereport(PANIC, (errcode_for_file_access(), errmsg("could not fsync file \"%s\": %m", XLogFileNameP(ThisTimeLineID, openLogSegNo)))); - pgstat_report_wait_end(); + bestatus_report_wait_end(); if (get_sync_bit(sync_method) != get_sync_bit(new_sync_method)) XLogFileClose(); } @@ -10299,7 +10300,7 @@ assign_xlog_sync_method(int new_sync_method, void *extra) void issue_xlog_fsync(int fd, XLogSegNo segno) { - pgstat_report_wait_start(WAIT_EVENT_WAL_SYNC); + bestatus_report_wait_start(WAIT_EVENT_WAL_SYNC); switch (sync_method) { case SYNC_METHOD_FSYNC: @@ -10335,7 +10336,7 @@ issue_xlog_fsync(int fd, XLogSegNo segno) elog(PANIC, "unrecognized wal_sync_method: %d", sync_method); break; } - pgstat_report_wait_end(); + bestatus_report_wait_end(); } /* @@ -11835,14 +11836,14 @@ retry: goto next_record_is_invalid; } - pgstat_report_wait_start(WAIT_EVENT_WAL_READ); + bestatus_report_wait_start(WAIT_EVENT_WAL_READ); r = read(readFile, readBuf, XLOG_BLCKSZ); if (r != XLOG_BLCKSZ) { char fname[MAXFNAMELEN]; int save_errno = errno; - pgstat_report_wait_end(); + bestatus_report_wait_end(); XLogFileName(fname, curFileTLI, readSegNo, wal_segment_size); if (r < 0) { @@ -11859,7 +11860,7 @@ retry: fname, readOff, r, (Size) XLOG_BLCKSZ))); goto next_record_is_invalid; } - pgstat_report_wait_end(); + bestatus_report_wait_end(); Assert(targetSegNo == readSegNo); Assert(targetPageOff == readOff); diff --git a/src/backend/access/transam/xlogfuncs.c b/src/backend/access/transam/xlogfuncs.c index a31adcca5e..b72da3f45f 100644 --- a/src/backend/access/transam/xlogfuncs.c +++ b/src/backend/access/transam/xlogfuncs.c @@ -23,9 +23,9 @@ #include "access/xlog_internal.h" #include "access/xlogutils.h" #include "catalog/pg_type.h" +#include "bestatus.h" #include "funcapi.h" #include "miscadmin.h" -#include "pgstat.h" #include "replication/walreceiver.h" #include "storage/smgr.h" #include "utils/builtins.h" diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c index 4ecdc9220f..1d9e1ca2b9 100644 --- a/src/backend/access/transam/xlogutils.c +++ b/src/backend/access/transam/xlogutils.c @@ -23,8 +23,8 @@ #include "access/xlog.h" #include "access/xlog_internal.h" #include "access/xlogutils.h" +#include "bestatus.h" #include "miscadmin.h" -#include "pgstat.h" #include "storage/smgr.h" #include "utils/guc.h" #include "utils/hsearch.h" @@ -736,9 +736,9 @@ XLogRead(char *buf, int segsize, TimeLineID tli, XLogRecPtr startptr, else segbytes = nbytes; - pgstat_report_wait_start(WAIT_EVENT_WAL_READ); + bestatus_report_wait_start(WAIT_EVENT_WAL_READ); readbytes = read(sendFile, p, segbytes); - pgstat_report_wait_end(); + bestatus_report_wait_end(); if (readbytes <= 0) { char path[MAXPGPATH]; diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c index dab0addd8b..1053985670 100644 --- a/src/backend/bootstrap/bootstrap.c +++ b/src/backend/bootstrap/bootstrap.c @@ -20,6 +20,7 @@ #include "access/htup_details.h" #include "access/xact.h" #include "access/xlog_internal.h" +#include "bestatus.h" #include "bootstrap/bootstrap.h" #include "catalog/index.h" #include "catalog/pg_collation.h" @@ -322,22 +323,22 @@ AuxiliaryProcessMain(int argc, char *argv[]) switch (MyAuxProcType) { case StartupProcess: - statmsg = pgstat_get_backend_desc(B_STARTUP); + statmsg = bestatus_get_backend_desc(B_STARTUP); break; case BgWriterProcess: - statmsg = pgstat_get_backend_desc(B_BG_WRITER); - break; - case ArchiverProcess: - statmsg = pgstat_get_backend_desc(B_ARCHIVER); + statmsg = bestatus_get_backend_desc(B_BG_WRITER); break; case CheckpointerProcess: - statmsg = pgstat_get_backend_desc(B_CHECKPOINTER); + statmsg = bestatus_get_backend_desc(B_CHECKPOINTER); break; case WalWriterProcess: - statmsg = pgstat_get_backend_desc(B_WAL_WRITER); + statmsg = bestatus_get_backend_desc(B_WAL_WRITER); break; case WalReceiverProcess: - statmsg = pgstat_get_backend_desc(B_WAL_RECEIVER); + statmsg = bestatus_get_backend_desc(B_WAL_RECEIVER); + break; + case ArchiverProcess: + statmsg = bestatus_get_backend_desc(B_ARCHIVER); break; default: statmsg = "??? process"; @@ -416,7 +417,8 @@ AuxiliaryProcessMain(int argc, char *argv[]) /* Initialize backend status information */ pgstat_initialize(); - pgstat_bestart(); + bestatus_initialize(); + bestatus_bestart(); /* register a before-shutdown callback for LWLock cleanup */ before_shmem_exit(ShutdownAuxiliaryProcess, 0); @@ -583,7 +585,7 @@ ShutdownAuxiliaryProcess(int code, Datum arg) { LWLockReleaseAll(); ConditionVariableCancelSleep(); - pgstat_report_wait_end(); + bestatus_report_wait_end(); } /* ---------------------------------------------------------------- diff --git a/src/backend/commands/vacuumlazy.c b/src/backend/commands/vacuumlazy.c index 8996d366e9..6a14165907 100644 --- a/src/backend/commands/vacuumlazy.c +++ b/src/backend/commands/vacuumlazy.c @@ -44,6 +44,7 @@ #include "access/transam.h" #include "access/visibilitymap.h" #include "access/xlog.h" +#include "bestatus.h" #include "catalog/storage.h" #include "commands/dbcommands.h" #include "commands/progress.h" @@ -223,7 +224,7 @@ lazy_vacuum_rel(Relation onerel, int options, VacuumParams *params, else elevel = DEBUG2; - pgstat_progress_start_command(PROGRESS_COMMAND_VACUUM, + bestatus_progress_start_command(PROGRESS_COMMAND_VACUUM, RelationGetRelid(onerel)); vac_strategy = bstrategy; @@ -290,7 +291,7 @@ lazy_vacuum_rel(Relation onerel, int options, VacuumParams *params, lazy_truncate_heap(onerel, vacrelstats); /* Report that we are now doing final cleanup */ - pgstat_progress_update_param(PROGRESS_VACUUM_PHASE, + bestatus_progress_update_param(PROGRESS_VACUUM_PHASE, PROGRESS_VACUUM_PHASE_FINAL_CLEANUP); /* @@ -343,7 +344,7 @@ lazy_vacuum_rel(Relation onerel, int options, VacuumParams *params, onerel->rd_rel->relisshared, new_live_tuples, vacrelstats->new_dead_tuples); - pgstat_progress_end_command(); + bestatus_progress_end_command(); /* and log the action if appropriate */ if (IsAutoVacuumWorkerProcess() && params->log_min_duration >= 0) @@ -537,7 +538,7 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats *vacrelstats, initprog_val[0] = PROGRESS_VACUUM_PHASE_SCAN_HEAP; initprog_val[1] = nblocks; initprog_val[2] = vacrelstats->max_dead_tuples; - pgstat_progress_update_multi_param(3, initprog_index, initprog_val); + bestatus_progress_update_multi_param(3, initprog_index, initprog_val); /* * Except when aggressive is set, we want to skip pages that are @@ -633,7 +634,7 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats *vacrelstats, #define FORCE_CHECK_PAGE() \ (blkno == nblocks - 1 && should_attempt_truncation(vacrelstats)) - pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_SCANNED, blkno); + bestatus_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_SCANNED, blkno); if (blkno == next_unskippable_block) { @@ -739,7 +740,7 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats *vacrelstats, vacuum_log_cleanup_info(onerel, vacrelstats); /* Report that we are now vacuuming indexes */ - pgstat_progress_update_param(PROGRESS_VACUUM_PHASE, + bestatus_progress_update_param(PROGRESS_VACUUM_PHASE, PROGRESS_VACUUM_PHASE_VACUUM_INDEX); /* Remove index entries */ @@ -751,12 +752,12 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats *vacrelstats, /* * Report that we are now vacuuming the heap. We also increase * the number of index scans here; note that by using - * pgstat_progress_update_multi_param we can update both + * bestatus_progress_update_multi_param we can update both * parameters atomically. */ hvp_val[0] = PROGRESS_VACUUM_PHASE_VACUUM_HEAP; hvp_val[1] = vacrelstats->num_index_scans + 1; - pgstat_progress_update_multi_param(2, hvp_index, hvp_val); + bestatus_progress_update_multi_param(2, hvp_index, hvp_val); /* Remove tuples from heap */ lazy_vacuum_heap(onerel, vacrelstats); @@ -777,7 +778,7 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats *vacrelstats, next_fsm_block_to_vacuum = blkno; /* Report that we are once again scanning the heap */ - pgstat_progress_update_param(PROGRESS_VACUUM_PHASE, + bestatus_progress_update_param(PROGRESS_VACUUM_PHASE, PROGRESS_VACUUM_PHASE_SCAN_HEAP); } @@ -1343,7 +1344,7 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats *vacrelstats, } /* report that everything is scanned and vacuumed */ - pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_SCANNED, blkno); + bestatus_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_SCANNED, blkno); pfree(frozen); @@ -1384,7 +1385,7 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats *vacrelstats, vacuum_log_cleanup_info(onerel, vacrelstats); /* Report that we are now vacuuming indexes */ - pgstat_progress_update_param(PROGRESS_VACUUM_PHASE, + bestatus_progress_update_param(PROGRESS_VACUUM_PHASE, PROGRESS_VACUUM_PHASE_VACUUM_INDEX); /* Remove index entries */ @@ -1396,10 +1397,10 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats *vacrelstats, /* Report that we are now vacuuming the heap */ hvp_val[0] = PROGRESS_VACUUM_PHASE_VACUUM_HEAP; hvp_val[1] = vacrelstats->num_index_scans + 1; - pgstat_progress_update_multi_param(2, hvp_index, hvp_val); + bestatus_progress_update_multi_param(2, hvp_index, hvp_val); /* Remove tuples from heap */ - pgstat_progress_update_param(PROGRESS_VACUUM_PHASE, + bestatus_progress_update_param(PROGRESS_VACUUM_PHASE, PROGRESS_VACUUM_PHASE_VACUUM_HEAP); lazy_vacuum_heap(onerel, vacrelstats); vacrelstats->num_index_scans++; @@ -1413,8 +1414,8 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats *vacrelstats, FreeSpaceMapVacuumRange(onerel, next_fsm_block_to_vacuum, blkno); /* report all blocks vacuumed; and that we're cleaning up */ - pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_VACUUMED, blkno); - pgstat_progress_update_param(PROGRESS_VACUUM_PHASE, + bestatus_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_VACUUMED, blkno); + bestatus_progress_update_param(PROGRESS_VACUUM_PHASE, PROGRESS_VACUUM_PHASE_INDEX_CLEANUP); /* Do post-vacuum cleanup and statistics update for each index */ @@ -1548,7 +1549,7 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer, TransactionId visibility_cutoff_xid; bool all_frozen; - pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_VACUUMED, blkno); + bestatus_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_VACUUMED, blkno); START_CRIT_SECTION(); @@ -1825,7 +1826,7 @@ lazy_truncate_heap(Relation onerel, LVRelStats *vacrelstats) pg_rusage_init(&ru0); /* Report that we are now truncating */ - pgstat_progress_update_param(PROGRESS_VACUUM_PHASE, + bestatus_progress_update_param(PROGRESS_VACUUM_PHASE, PROGRESS_VACUUM_PHASE_TRUNCATE); /* @@ -2132,7 +2133,7 @@ lazy_record_dead_tuple(LVRelStats *vacrelstats, { vacrelstats->dead_tuples[vacrelstats->num_dead_tuples] = *itemptr; vacrelstats->num_dead_tuples++; - pgstat_progress_update_param(PROGRESS_VACUUM_NUM_DEAD_TUPLES, + bestatus_progress_update_param(PROGRESS_VACUUM_NUM_DEAD_TUPLES, vacrelstats->num_dead_tuples); } } diff --git a/src/backend/executor/execParallel.c b/src/backend/executor/execParallel.c index 13ef232d39..b368da619f 100644 --- a/src/backend/executor/execParallel.c +++ b/src/backend/executor/execParallel.c @@ -48,7 +48,7 @@ #include "utils/lsyscache.h" #include "utils/memutils.h" #include "utils/snapmgr.h" -#include "pgstat.h" +#include "bestatus.h" /* * Magic numbers for parallel executor communication. We use constants @@ -1358,7 +1358,7 @@ ParallelQueryMain(dsm_segment *seg, shm_toc *toc) debug_query_string = queryDesc->sourceText; /* Report workers' query for monitoring purposes */ - pgstat_report_activity(STATE_RUNNING, debug_query_string); + bestatus_report_activity(STATE_RUNNING, debug_query_string); /* Attach to the dynamic shared memory area. */ area_space = shm_toc_lookup(toc, PARALLEL_KEY_DSA, false); diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c index 304ef07f2c..856f497d51 100644 --- a/src/backend/executor/nodeBitmapHeapscan.c +++ b/src/backend/executor/nodeBitmapHeapscan.c @@ -40,6 +40,7 @@ #include "access/relscan.h" #include "access/transam.h" #include "access/visibilitymap.h" +#include "bestatus.h" #include "executor/execdebug.h" #include "executor/nodeBitmapHeapscan.h" #include "miscadmin.h" diff --git a/src/backend/executor/nodeGather.c b/src/backend/executor/nodeGather.c index ad16c783bd..281f27998a 100644 --- a/src/backend/executor/nodeGather.c +++ b/src/backend/executor/nodeGather.c @@ -32,6 +32,7 @@ #include "access/relscan.h" #include "access/xact.h" +#include "bestatus.h" #include "executor/execdebug.h" #include "executor/execParallel.h" #include "executor/nodeGather.h" @@ -39,7 +40,6 @@ #include "executor/tqueue.h" #include "miscadmin.h" #include "optimizer/planmain.h" -#include "pgstat.h" #include "utils/memutils.h" #include "utils/rel.h" diff --git a/src/backend/executor/nodeHash.c b/src/backend/executor/nodeHash.c index 6ffaa751f2..7a850e8192 100644 --- a/src/backend/executor/nodeHash.c +++ b/src/backend/executor/nodeHash.c @@ -28,6 +28,7 @@ #include "access/htup_details.h" #include "access/parallel.h" +#include "bestatus.h" #include "catalog/pg_statistic.h" #include "commands/tablespace.h" #include "executor/execdebug.h" @@ -35,7 +36,6 @@ #include "executor/nodeHash.h" #include "executor/nodeHashjoin.h" #include "miscadmin.h" -#include "pgstat.h" #include "port/atomics.h" #include "utils/dynahash.h" #include "utils/memutils.h" diff --git a/src/backend/executor/nodeHashjoin.c b/src/backend/executor/nodeHashjoin.c index dd94cffbd1..91d3a0bbbd 100644 --- a/src/backend/executor/nodeHashjoin.c +++ b/src/backend/executor/nodeHashjoin.c @@ -108,12 +108,12 @@ #include "access/htup_details.h" #include "access/parallel.h" +#include "bestatus.h" #include "executor/executor.h" #include "executor/hashjoin.h" #include "executor/nodeHash.h" #include "executor/nodeHashjoin.h" #include "miscadmin.h" -#include "pgstat.h" #include "utils/memutils.h" #include "utils/sharedtuplestore.h" diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c index 6a576572bb..5a304c7405 100644 --- a/src/backend/libpq/be-secure-openssl.c +++ b/src/backend/libpq/be-secure-openssl.c @@ -36,9 +36,9 @@ #include #endif +#include "bestatus.h" #include "libpq/libpq.h" #include "miscadmin.h" -#include "pgstat.h" #include "storage/fd.h" #include "storage/latch.h" #include "tcop/tcopprot.h" diff --git a/src/backend/libpq/be-secure.c b/src/backend/libpq/be-secure.c index 4eb21fe89d..517b22a694 100644 --- a/src/backend/libpq/be-secure.c +++ b/src/backend/libpq/be-secure.c @@ -29,9 +29,9 @@ #include #endif +#include "bestatus.h" #include "libpq/libpq.h" #include "miscadmin.h" -#include "pgstat.h" #include "tcop/tcopprot.h" #include "utils/memutils.h" #include "storage/ipc.h" diff --git a/src/backend/libpq/pqmq.c b/src/backend/libpq/pqmq.c index 6eaed5bf0c..5906682fbf 100644 --- a/src/backend/libpq/pqmq.c +++ b/src/backend/libpq/pqmq.c @@ -13,11 +13,11 @@ #include "postgres.h" +#include "bestatus.h" #include "libpq/libpq.h" #include "libpq/pqformat.h" #include "libpq/pqmq.h" #include "miscadmin.h" -#include "pgstat.h" #include "tcop/tcopprot.h" #include "utils/builtins.h" diff --git a/src/backend/postmaster/Makefile b/src/backend/postmaster/Makefile index 71c23211b2..311e63017d 100644 --- a/src/backend/postmaster/Makefile +++ b/src/backend/postmaster/Makefile @@ -13,6 +13,6 @@ top_builddir = ../../.. include $(top_builddir)/src/Makefile.global OBJS = autovacuum.o bgworker.o bgwriter.o checkpointer.o fork_process.o \ - pgarch.o pgstat.o postmaster.o startup.o syslogger.o walwriter.o + pgarch.o postmaster.o startup.o syslogger.o walwriter.o include $(top_srcdir)/src/backend/common.mk diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 10e707e9a1..2005021468 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -71,6 +71,7 @@ #include "access/reloptions.h" #include "access/transam.h" #include "access/xact.h" +#include "bestatus.h" #include "catalog/dependency.h" #include "catalog/namespace.h" #include "catalog/pg_database.h" @@ -436,7 +437,7 @@ AutoVacLauncherMain(int argc, char *argv[]) am_autovacuum_launcher = true; /* Identify myself via ps */ - init_ps_display(pgstat_get_backend_desc(B_AUTOVAC_LAUNCHER), "", "", ""); + init_ps_display(bestatus_get_backend_desc(B_AUTOVAC_LAUNCHER), "", "", ""); ereport(DEBUG1, (errmsg("autovacuum launcher started"))); @@ -519,7 +520,7 @@ AutoVacLauncherMain(int argc, char *argv[]) * transaction. */ LWLockReleaseAll(); - pgstat_report_wait_end(); + bestatus_report_wait_end(); AbortBufferIO(); UnlockBuffers(); /* this is probably dead code, but let's be safe: */ @@ -1530,7 +1531,7 @@ AutoVacWorkerMain(int argc, char *argv[]) am_autovacuum_worker = true; /* Identify myself via ps */ - init_ps_display(pgstat_get_backend_desc(B_AUTOVAC_WORKER), "", "", ""); + init_ps_display(bestatus_get_backend_desc(B_AUTOVAC_WORKER), "", "", ""); SetProcessingMode(InitProcessing); @@ -3173,7 +3174,7 @@ autovac_report_activity(autovac_table *tab) /* Set statement_timestamp() to current time for pg_stat_activity */ SetCurrentStatementStartTimestamp(); - pgstat_report_activity(STATE_RUNNING, activity); + bestatus_report_activity(STATE_RUNNING, activity); } /* @@ -3212,7 +3213,7 @@ autovac_report_workitem(AutoVacuumWorkItem *workitem, /* Set statement_timestamp() to current time for pg_stat_activity */ SetCurrentStatementStartTimestamp(); - pgstat_report_activity(STATE_RUNNING, activity); + bestatus_report_activity(STATE_RUNNING, activity); } /* diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c index d2b695e146..01eaa187ff 100644 --- a/src/backend/postmaster/bgworker.c +++ b/src/backend/postmaster/bgworker.c @@ -16,8 +16,8 @@ #include "libpq/pqsignal.h" #include "access/parallel.h" +#include "bestatus.h" #include "miscadmin.h" -#include "pgstat.h" #include "port/atomics.h" #include "postmaster/bgworker_internals.h" #include "postmaster/postmaster.h" diff --git a/src/backend/postmaster/bgwriter.c b/src/backend/postmaster/bgwriter.c index a4b1079e60..36f3c91286 100644 --- a/src/backend/postmaster/bgwriter.c +++ b/src/backend/postmaster/bgwriter.c @@ -40,6 +40,7 @@ #include "access/xlog.h" #include "access/xlog_internal.h" +#include "bestatus.h" #include "libpq/pqsignal.h" #include "miscadmin.h" #include "pgstat.h" @@ -222,7 +223,7 @@ BackgroundWriterMain(void) smgrcloseall(); /* Report wait end here, when there is no further possibility of wait */ - pgstat_report_wait_end(); + bestatus_report_wait_end(); } /* We can now handle ereport(ERROR) */ diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c index 9235390bc6..02aa48743f 100644 --- a/src/backend/postmaster/checkpointer.c +++ b/src/backend/postmaster/checkpointer.c @@ -43,6 +43,7 @@ #include "access/xlog.h" #include "access/xlog_internal.h" +#include "bestatus.h" #include "libpq/pqsignal.h" #include "miscadmin.h" #include "pgstat.h" @@ -266,7 +267,7 @@ CheckpointerMain(void) */ LWLockReleaseAll(); ConditionVariableCancelSleep(); - pgstat_report_wait_end(); + bestatus_report_wait_end(); AbortBufferIO(); UnlockBuffers(); ReleaseAuxProcessResources(false); diff --git a/src/backend/postmaster/pgarch.c b/src/backend/postmaster/pgarch.c index 7d4e528096..deec58b057 100644 --- a/src/backend/postmaster/pgarch.c +++ b/src/backend/postmaster/pgarch.c @@ -34,6 +34,7 @@ #include "access/xlog.h" #include "access/xlog_internal.h" +#include "bestatus.h" #include "libpq/pqsignal.h" #include "miscadmin.h" #include "pgstat.h" diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 559aeedb6e..db343b86c6 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -95,6 +95,7 @@ #include "access/transam.h" #include "access/xlog.h" +#include "bestatus.h" #include "bootstrap/bootstrap.h" #include "catalog/pg_control.h" #include "common/file_perm.h" @@ -3534,7 +3535,7 @@ LogChildExit(int lev, const char *procname, int pid, int exitstatus) const char *activity = NULL; if (!EXIT_STATUS_0(exitstatus)) - activity = pgstat_get_crashed_backend_activity(pid, + activity = bestatus_get_crashed_backend_activity(pid, activity_buffer, sizeof(activity_buffer)); @@ -4254,7 +4255,7 @@ BackendInitialize(Port *port) * init_ps_display() to avoid abusing the parameters like this. */ if (am_walsender) - init_ps_display(pgstat_get_backend_desc(B_WAL_SENDER), port->user_name, remote_ps_data, + init_ps_display(bestatus_get_backend_desc(B_WAL_SENDER), port->user_name, remote_ps_data, update_process_title ? "authentication" : ""); else init_ps_display(port->user_name, port->database_name, remote_ps_data, diff --git a/src/backend/postmaster/syslogger.c b/src/backend/postmaster/syslogger.c index 29bdcec895..d23987b20e 100644 --- a/src/backend/postmaster/syslogger.c +++ b/src/backend/postmaster/syslogger.c @@ -31,11 +31,11 @@ #include #include +#include "bestatus.h" #include "lib/stringinfo.h" #include "libpq/pqsignal.h" #include "miscadmin.h" #include "nodes/pg_list.h" -#include "pgstat.h" #include "pgtime.h" #include "postmaster/fork_process.h" #include "postmaster/postmaster.h" diff --git a/src/backend/postmaster/walwriter.c b/src/backend/postmaster/walwriter.c index fb66bceeed..b2c59d9d5f 100644 --- a/src/backend/postmaster/walwriter.c +++ b/src/backend/postmaster/walwriter.c @@ -45,9 +45,9 @@ #include #include "access/xlog.h" +#include "bestatus.h" #include "libpq/pqsignal.h" #include "miscadmin.h" -#include "pgstat.h" #include "postmaster/walwriter.h" #include "storage/bufmgr.h" #include "storage/condition_variable.h" @@ -163,7 +163,7 @@ WalWriterMain(void) */ LWLockReleaseAll(); ConditionVariableCancelSleep(); - pgstat_report_wait_end(); + bestatus_report_wait_end(); AbortBufferIO(); UnlockBuffers(); ReleaseAuxProcessResources(false); diff --git a/src/backend/replication/basebackup.c b/src/backend/replication/basebackup.c index 20cf33354a..1ce0809361 100644 --- a/src/backend/replication/basebackup.c +++ b/src/backend/replication/basebackup.c @@ -17,6 +17,7 @@ #include #include "access/xlog_internal.h" /* for pg_start/stop_backup */ +#include "bestatus.h" #include "catalog/pg_type.h" #include "common/file_perm.h" #include "lib/stringinfo.h" @@ -25,7 +26,6 @@ #include "miscadmin.h" #include "nodes/pg_list.h" #include "pgtar.h" -#include "pgstat.h" #include "port.h" #include "postmaster/syslogger.h" #include "replication/basebackup.h" diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c index 1e1695ef4f..b992473fd4 100644 --- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c +++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c @@ -22,11 +22,11 @@ #include "libpq-fe.h" #include "pqexpbuffer.h" #include "access/xlog.h" +#include "bestatus.h" #include "catalog/pg_type.h" #include "funcapi.h" #include "mb/pg_wchar.h" #include "miscadmin.h" -#include "pgstat.h" #include "replication/walreceiver.h" #include "utils/builtins.h" #include "utils/memutils.h" diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c index ada16adb67..bf7ac927f7 100644 --- a/src/backend/replication/logical/launcher.c +++ b/src/backend/replication/logical/launcher.c @@ -19,7 +19,7 @@ #include "funcapi.h" #include "miscadmin.h" -#include "pgstat.h" +#include "bestatus.h" #include "access/heapam.h" #include "access/htup.h" diff --git a/src/backend/replication/logical/origin.c b/src/backend/replication/logical/origin.c index bf97dcdee4..a60ef0a9f1 100644 --- a/src/backend/replication/logical/origin.c +++ b/src/backend/replication/logical/origin.c @@ -77,13 +77,12 @@ #include "access/heapam.h" #include "access/htup_details.h" #include "access/xact.h" - +#include "bestatus.h" #include "catalog/indexing.h" #include "nodes/execnodes.h" #include "replication/origin.h" #include "replication/logical.h" -#include "pgstat.h" #include "storage/fd.h" #include "storage/ipc.h" #include "storage/lmgr.h" diff --git a/src/backend/replication/logical/reorderbuffer.c b/src/backend/replication/logical/reorderbuffer.c index bed63c768e..c8ffd885f5 100644 --- a/src/backend/replication/logical/reorderbuffer.c +++ b/src/backend/replication/logical/reorderbuffer.c @@ -61,10 +61,10 @@ #include "access/tuptoaster.h" #include "access/xact.h" #include "access/xlog_internal.h" +#include "bestatus.h" #include "catalog/catalog.h" #include "lib/binaryheap.h" #include "miscadmin.h" -#include "pgstat.h" #include "replication/logical.h" #include "replication/reorderbuffer.h" #include "replication/slot.h" @@ -2494,7 +2494,7 @@ ReorderBufferSerializeChange(ReorderBuffer *rb, ReorderBufferTXN *txn, ondisk->size = sz; errno = 0; - pgstat_report_wait_start(WAIT_EVENT_REORDER_BUFFER_WRITE); + bestatus_report_wait_start(WAIT_EVENT_REORDER_BUFFER_WRITE); if (write(fd, rb->outbuf, ondisk->size) != ondisk->size) { int save_errno = errno; @@ -2508,7 +2508,7 @@ ReorderBufferSerializeChange(ReorderBuffer *rb, ReorderBufferTXN *txn, errmsg("could not write to data file for XID %u: %m", txn->xid))); } - pgstat_report_wait_end(); + bestatus_report_wait_end(); Assert(ondisk->change.action == change->action); } @@ -2583,9 +2583,9 @@ ReorderBufferRestoreChanges(ReorderBuffer *rb, ReorderBufferTXN *txn, * end of this file. */ ReorderBufferSerializeReserve(rb, sizeof(ReorderBufferDiskChange)); - pgstat_report_wait_start(WAIT_EVENT_REORDER_BUFFER_READ); + bestatus_report_wait_start(WAIT_EVENT_REORDER_BUFFER_READ); readBytes = read(*fd, rb->outbuf, sizeof(ReorderBufferDiskChange)); - pgstat_report_wait_end(); + bestatus_report_wait_end(); /* eof */ if (readBytes == 0) @@ -2612,10 +2612,10 @@ ReorderBufferRestoreChanges(ReorderBuffer *rb, ReorderBufferTXN *txn, sizeof(ReorderBufferDiskChange) + ondisk->size); ondisk = (ReorderBufferDiskChange *) rb->outbuf; - pgstat_report_wait_start(WAIT_EVENT_REORDER_BUFFER_READ); + bestatus_report_wait_start(WAIT_EVENT_REORDER_BUFFER_READ); readBytes = read(*fd, rb->outbuf + sizeof(ReorderBufferDiskChange), ondisk->size - sizeof(ReorderBufferDiskChange)); - pgstat_report_wait_end(); + bestatus_report_wait_end(); if (readBytes < 0) ereport(ERROR, @@ -3299,9 +3299,9 @@ ApplyLogicalMappingFile(HTAB *tuplecid_data, Oid relid, const char *fname) memset(&key, 0, sizeof(ReorderBufferTupleCidKey)); /* read all mappings till the end of the file */ - pgstat_report_wait_start(WAIT_EVENT_REORDER_LOGICAL_MAPPING_READ); + bestatus_report_wait_start(WAIT_EVENT_REORDER_LOGICAL_MAPPING_READ); readBytes = read(fd, &map, sizeof(LogicalRewriteMappingData)); - pgstat_report_wait_end(); + bestatus_report_wait_end(); if (readBytes < 0) ereport(ERROR, diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index a6cd6c67d1..e3c2d79919 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -126,7 +126,7 @@ #include "access/transam.h" #include "access/xact.h" -#include "pgstat.h" +#include "bestatus.h" #include "replication/logical.h" #include "replication/reorderbuffer.h" @@ -1610,7 +1610,7 @@ SnapBuildSerialize(SnapBuild *builder, XLogRecPtr lsn) (errmsg("could not open file \"%s\": %m", path))); errno = 0; - pgstat_report_wait_start(WAIT_EVENT_SNAPBUILD_WRITE); + bestatus_report_wait_start(WAIT_EVENT_SNAPBUILD_WRITE); if ((write(fd, ondisk, needed_length)) != needed_length) { int save_errno = errno; @@ -1623,7 +1623,7 @@ SnapBuildSerialize(SnapBuild *builder, XLogRecPtr lsn) (errcode_for_file_access(), errmsg("could not write to file \"%s\": %m", tmppath))); } - pgstat_report_wait_end(); + bestatus_report_wait_end(); /* * fsync the file before renaming so that even if we crash after this we @@ -1633,7 +1633,7 @@ SnapBuildSerialize(SnapBuild *builder, XLogRecPtr lsn) * some noticeable overhead since it's performed synchronously during * decoding? */ - pgstat_report_wait_start(WAIT_EVENT_SNAPBUILD_SYNC); + bestatus_report_wait_start(WAIT_EVENT_SNAPBUILD_SYNC); if (pg_fsync(fd) != 0) { int save_errno = errno; @@ -1644,7 +1644,7 @@ SnapBuildSerialize(SnapBuild *builder, XLogRecPtr lsn) (errcode_for_file_access(), errmsg("could not fsync file \"%s\": %m", tmppath))); } - pgstat_report_wait_end(); + bestatus_report_wait_end(); CloseTransientFile(fd); fsync_fname("pg_logical/snapshots", true); @@ -1719,9 +1719,9 @@ SnapBuildRestore(SnapBuild *builder, XLogRecPtr lsn) /* read statically sized portion of snapshot */ - pgstat_report_wait_start(WAIT_EVENT_SNAPBUILD_READ); + bestatus_report_wait_start(WAIT_EVENT_SNAPBUILD_READ); readBytes = read(fd, &ondisk, SnapBuildOnDiskConstantSize); - pgstat_report_wait_end(); + bestatus_report_wait_end(); if (readBytes != SnapBuildOnDiskConstantSize) { int save_errno = errno; @@ -1759,9 +1759,9 @@ SnapBuildRestore(SnapBuild *builder, XLogRecPtr lsn) SnapBuildOnDiskConstantSize - SnapBuildOnDiskNotChecksummedSize); /* read SnapBuild */ - pgstat_report_wait_start(WAIT_EVENT_SNAPBUILD_READ); + bestatus_report_wait_start(WAIT_EVENT_SNAPBUILD_READ); readBytes = read(fd, &ondisk.builder, sizeof(SnapBuild)); - pgstat_report_wait_end(); + bestatus_report_wait_end(); if (readBytes != sizeof(SnapBuild)) { int save_errno = errno; @@ -1787,9 +1787,9 @@ SnapBuildRestore(SnapBuild *builder, XLogRecPtr lsn) sz = sizeof(TransactionId) * ondisk.builder.was_running.was_xcnt_space; ondisk.builder.was_running.was_xip = MemoryContextAllocZero(builder->context, sz); - pgstat_report_wait_start(WAIT_EVENT_SNAPBUILD_READ); + bestatus_report_wait_start(WAIT_EVENT_SNAPBUILD_READ); readBytes = read(fd, ondisk.builder.was_running.was_xip, sz); - pgstat_report_wait_end(); + bestatus_report_wait_end(); if (readBytes != sz) { int save_errno = errno; @@ -1814,9 +1814,9 @@ SnapBuildRestore(SnapBuild *builder, XLogRecPtr lsn) /* restore committed xacts information */ sz = sizeof(TransactionId) * ondisk.builder.committed.xcnt; ondisk.builder.committed.xip = MemoryContextAllocZero(builder->context, sz); - pgstat_report_wait_start(WAIT_EVENT_SNAPBUILD_READ); + bestatus_report_wait_start(WAIT_EVENT_SNAPBUILD_READ); readBytes = read(fd, ondisk.builder.committed.xip, sz); - pgstat_report_wait_end(); + bestatus_report_wait_end(); if (readBytes != sz) { int save_errno = errno; diff --git a/src/backend/replication/logical/tablesync.c b/src/backend/replication/logical/tablesync.c index 862582da23..670552593f 100644 --- a/src/backend/replication/logical/tablesync.c +++ b/src/backend/replication/logical/tablesync.c @@ -86,25 +86,27 @@ #include "postgres.h" #include "miscadmin.h" -#include "pgstat.h" #include "access/xact.h" +#include "bestatus.h" + #include "catalog/pg_subscription_rel.h" #include "catalog/pg_type.h" #include "commands/copy.h" #include "parser/parse_relation.h" +#include "pgstat.h" #include "replication/logicallauncher.h" #include "replication/logicalrelation.h" #include "replication/walreceiver.h" #include "replication/worker_internal.h" -#include "utils/snapmgr.h" #include "storage/ipc.h" +#include "utils/snapmgr.h" #include "utils/builtins.h" #include "utils/lsyscache.h" #include "utils/memutils.h" diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c index 087850d089..4b7ae0d7ff 100644 --- a/src/backend/replication/logical/worker.c +++ b/src/backend/replication/logical/worker.c @@ -23,13 +23,11 @@ #include "postgres.h" -#include "miscadmin.h" -#include "pgstat.h" -#include "funcapi.h" - #include "access/xact.h" #include "access/xlog_internal.h" +#include "bestatus.h" + #include "catalog/catalog.h" #include "catalog/namespace.h" #include "catalog/pg_subscription.h" @@ -41,17 +39,20 @@ #include "executor/executor.h" #include "executor/nodeModifyTable.h" +#include "funcapi.h" + #include "libpq/pqformat.h" #include "libpq/pqsignal.h" #include "mb/pg_wchar.h" +#include "miscadmin.h" #include "nodes/makefuncs.h" #include "optimizer/planner.h" #include "parser/parse_relation.h" - +#include "pgstat.h" #include "postmaster/bgworker.h" #include "postmaster/postmaster.h" #include "postmaster/walwriter.h" @@ -463,7 +464,7 @@ apply_handle_begin(StringInfo s) in_remote_transaction = true; - pgstat_report_activity(STATE_RUNNING, NULL); + bestatus_report_activity(STATE_RUNNING, NULL); } /* @@ -507,7 +508,7 @@ apply_handle_commit(StringInfo s) /* Process any tables that are being synchronized in parallel. */ process_syncing_tables(commit_data.end_lsn); - pgstat_report_activity(STATE_IDLE, NULL); + bestatus_report_activity(STATE_IDLE, NULL); } /* @@ -1113,7 +1114,7 @@ LogicalRepApplyLoop(XLogRecPtr last_received) ALLOCSET_DEFAULT_SIZES); /* mark as idle, before starting to loop */ - pgstat_report_activity(STATE_IDLE, NULL); + bestatus_report_activity(STATE_IDLE, NULL); for (;;) { diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c index b30332abad..eed9d65947 100644 --- a/src/backend/replication/slot.c +++ b/src/backend/replication/slot.c @@ -41,9 +41,9 @@ #include "access/transam.h" #include "access/xlog_internal.h" +#include "bestatus.h" #include "common/string.h" #include "miscadmin.h" -#include "pgstat.h" #include "replication/slot.h" #include "storage/fd.h" #include "storage/proc.h" @@ -1280,12 +1280,12 @@ SaveSlotToPath(ReplicationSlot *slot, const char *dir, int elevel) FIN_CRC32C(cp.checksum); errno = 0; - pgstat_report_wait_start(WAIT_EVENT_REPLICATION_SLOT_WRITE); + bestatus_report_wait_start(WAIT_EVENT_REPLICATION_SLOT_WRITE); if ((write(fd, &cp, sizeof(cp))) != sizeof(cp)) { int save_errno = errno; - pgstat_report_wait_end(); + bestatus_report_wait_end(); CloseTransientFile(fd); /* if write didn't set errno, assume problem is no disk space */ @@ -1296,15 +1296,15 @@ SaveSlotToPath(ReplicationSlot *slot, const char *dir, int elevel) tmppath))); return; } - pgstat_report_wait_end(); + bestatus_report_wait_end(); /* fsync the temporary file */ - pgstat_report_wait_start(WAIT_EVENT_REPLICATION_SLOT_SYNC); + bestatus_report_wait_start(WAIT_EVENT_REPLICATION_SLOT_SYNC); if (pg_fsync(fd) != 0) { int save_errno = errno; - pgstat_report_wait_end(); + bestatus_report_wait_end(); CloseTransientFile(fd); errno = save_errno; ereport(elevel, @@ -1313,7 +1313,7 @@ SaveSlotToPath(ReplicationSlot *slot, const char *dir, int elevel) tmppath))); return; } - pgstat_report_wait_end(); + bestatus_report_wait_end(); CloseTransientFile(fd); @@ -1392,7 +1392,7 @@ RestoreSlotFromDisk(const char *name) * Sync state file before we're reading from it. We might have crashed * while it wasn't synced yet and we shouldn't continue on that basis. */ - pgstat_report_wait_start(WAIT_EVENT_REPLICATION_SLOT_RESTORE_SYNC); + bestatus_report_wait_start(WAIT_EVENT_REPLICATION_SLOT_RESTORE_SYNC); if (pg_fsync(fd) != 0) { int save_errno = errno; @@ -1404,7 +1404,7 @@ RestoreSlotFromDisk(const char *name) errmsg("could not fsync file \"%s\": %m", path))); } - pgstat_report_wait_end(); + bestatus_report_wait_end(); /* Also sync the parent directory */ START_CRIT_SECTION(); @@ -1412,9 +1412,9 @@ RestoreSlotFromDisk(const char *name) END_CRIT_SECTION(); /* read part of statefile that's guaranteed to be version independent */ - pgstat_report_wait_start(WAIT_EVENT_REPLICATION_SLOT_READ); + bestatus_report_wait_start(WAIT_EVENT_REPLICATION_SLOT_READ); readBytes = read(fd, &cp, ReplicationSlotOnDiskConstantSize); - pgstat_report_wait_end(); + bestatus_report_wait_end(); if (readBytes != ReplicationSlotOnDiskConstantSize) { int saved_errno = errno; @@ -1455,11 +1455,11 @@ RestoreSlotFromDisk(const char *name) path, cp.length))); /* Now that we know the size, read the entire file */ - pgstat_report_wait_start(WAIT_EVENT_REPLICATION_SLOT_READ); + bestatus_report_wait_start(WAIT_EVENT_REPLICATION_SLOT_READ); readBytes = read(fd, (char *) &cp + ReplicationSlotOnDiskConstantSize, cp.length); - pgstat_report_wait_end(); + bestatus_report_wait_end(); if (readBytes != cp.length) { int saved_errno = errno; diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index af5ad5fe66..957aea0a7d 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -75,8 +75,8 @@ #include #include "access/xact.h" +#include "bestatus.h" #include "miscadmin.h" -#include "pgstat.h" #include "replication/syncrep.h" #include "replication/walsender.h" #include "replication/walsender_private.h" diff --git a/src/backend/replication/walreceiver.c b/src/backend/replication/walreceiver.c index 6f4b3538ac..0d65ed8f2a 100644 --- a/src/backend/replication/walreceiver.c +++ b/src/backend/replication/walreceiver.c @@ -50,6 +50,7 @@ #include "access/timeline.h" #include "access/transam.h" #include "access/xlog_internal.h" +#include "bestatus.h" #include "catalog/pg_authid.h" #include "catalog/pg_type.h" #include "common/ip.h" @@ -57,7 +58,6 @@ #include "libpq/pqformat.h" #include "libpq/pqsignal.h" #include "miscadmin.h" -#include "pgstat.h" #include "replication/walreceiver.h" #include "replication/walsender.h" #include "storage/ipc.h" diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c index 2683385ca6..6fc9a8f658 100644 --- a/src/backend/replication/walsender.c +++ b/src/backend/replication/walsender.c @@ -56,6 +56,7 @@ #include "access/xlog_internal.h" #include "access/xlogutils.h" +#include "bestatus.h" #include "catalog/pg_authid.h" #include "catalog/pg_type.h" #include "commands/dbcommands.h" @@ -65,7 +66,6 @@ #include "libpq/pqformat.h" #include "miscadmin.h" #include "nodes/replnodes.h" -#include "pgstat.h" #include "replication/basebackup.h" #include "replication/decode.h" #include "replication/logical.h" @@ -299,7 +299,7 @@ WalSndErrorCleanup(void) { LWLockReleaseAll(); ConditionVariableCancelSleep(); - pgstat_report_wait_end(); + bestatus_report_wait_end(); if (sendFile >= 0) { @@ -504,9 +504,9 @@ SendTimeLineHistory(TimeLineHistoryCmd *cmd) PGAlignedBlock rbuf; int nread; - pgstat_report_wait_start(WAIT_EVENT_WALSENDER_TIMELINE_HISTORY_READ); + bestatus_report_wait_start(WAIT_EVENT_WALSENDER_TIMELINE_HISTORY_READ); nread = read(fd, rbuf.data, sizeof(rbuf)); - pgstat_report_wait_end(); + bestatus_report_wait_end(); if (nread < 0) ereport(ERROR, (errcode_for_file_access(), @@ -1517,7 +1517,7 @@ exec_replication_command(const char *cmd_string) initStringInfo(&tmpbuf); /* Report to pgstat that this process is running */ - pgstat_report_activity(STATE_RUNNING, NULL); + bestatus_report_activity(STATE_RUNNING, NULL); switch (cmd_node->type) { @@ -1571,7 +1571,7 @@ exec_replication_command(const char *cmd_string) (errmsg("cannot execute SQL commands in WAL sender for physical replication"))); /* Report to pgstat that this process is now idle */ - pgstat_report_activity(STATE_IDLE, NULL); + bestatus_report_activity(STATE_IDLE, NULL); /* Tell the caller that this wasn't a WalSender command. */ return false; @@ -1589,7 +1589,7 @@ exec_replication_command(const char *cmd_string) EndCommand("SELECT", DestRemote); /* Report to pgstat that this process is now idle */ - pgstat_report_activity(STATE_IDLE, NULL); + bestatus_report_activity(STATE_IDLE, NULL); return true; } @@ -2442,9 +2442,9 @@ retry: else segbytes = nbytes; - pgstat_report_wait_start(WAIT_EVENT_WAL_READ); + bestatus_report_wait_start(WAIT_EVENT_WAL_READ); readbytes = read(sendFile, p, segbytes); - pgstat_report_wait_end(); + bestatus_report_wait_end(); if (readbytes < 0) { ereport(ERROR, diff --git a/src/backend/statmon/Makefile b/src/backend/statmon/Makefile new file mode 100644 index 0000000000..64a04878e3 --- /dev/null +++ b/src/backend/statmon/Makefile @@ -0,0 +1,17 @@ +#------------------------------------------------------------------------- +# +# Makefile-- +# Makefile for src/backend/statmon +# +# IDENTIFICATION +# src/backend/statmon/Makefile +# +#------------------------------------------------------------------------- + +subdir = src/backend/statmon +top_builddir = ../../.. +include $(top_builddir)/src/Makefile.global + +OBJS = pgstat.o bestatus.o + +include $(top_srcdir)/src/backend/common.mk diff --git a/src/backend/statmon/bestatus.c b/src/backend/statmon/bestatus.c new file mode 100644 index 0000000000..5fda088258 --- /dev/null +++ b/src/backend/statmon/bestatus.c @@ -0,0 +1,1759 @@ +/* ---------- + * bestatus.c + * + * Backend status monitor + * + * Status data is stored in shared memory. Every backends updates and read it + * individually. + * + * Copyright (c) 2001-2018, PostgreSQL Global Development Group + * + * src/backend/statmon/bestatus.c + * ---------- + */ +#include "postgres.h" + +#include "bestatus.h" + +#include "access/xact.h" +#include "libpq/libpq.h" +#include "miscadmin.h" +#include "postmaster/autovacuum.h" +#include "replication/walsender.h" +#include "storage/ipc.h" +#include "storage/lmgr.h" +#include "storage/sinvaladt.h" +#include "utils/ascii.h" +#include "utils/guc.h" +#include "utils/memutils.h" +#include "utils/probes.h" + + +/* Status for backends including auxiliary */ +static LocalPgBackendStatus *localBackendStatusTable = NULL; + +/* Total number of backends including auxiliary */ +static int localNumBackends = 0; + +/* ---------- + * Total number of backends including auxiliary + * + * We reserve a slot for each possible BackendId, plus one for each + * possible auxiliary process type. (This scheme assumes there is not + * more than one of any auxiliary process type at a time.) MaxBackends + * includes autovacuum workers and background workers as well. + * ---------- + */ +#define NumBackendStatSlots (MaxBackends + NUM_AUXPROCTYPES) + + +/* ---------- + * GUC parameters + * ---------- + */ +bool bestatus_track_activities = false; +int bestatus_track_activity_query_size = 1024; + +static MemoryContext pgBeStatLocalContext = NULL; + +/* ------------------------------------------------------------ + * Functions for management of the shared-memory PgBackendStatus array + * ------------------------------------------------------------ + */ + +static PgBackendStatus *BackendStatusArray = NULL; +static PgBackendStatus *MyBEEntry = NULL; +static char *BackendAppnameBuffer = NULL; +static char *BackendClientHostnameBuffer = NULL; +static char *BackendActivityBuffer = NULL; +static Size BackendActivityBufferSize = 0; +#ifdef USE_SSL +static PgBackendSSLStatus *BackendSslStatusBuffer = NULL; +#endif + +static const char *bestatus_get_wait_activity(WaitEventActivity w); +static const char *bestatus_get_wait_client(WaitEventClient w); +static const char *bestatus_get_wait_ipc(WaitEventIPC w); +static const char *bestatus_get_wait_timeout(WaitEventTimeout w); +static const char *bestatus_get_wait_io(WaitEventIO w); +static void bestatus_setup_memcxt(void); +static void bestatus_beshutdown_hook(int code, Datum arg); +/* + * Report shared-memory space needed by CreateSharedBackendStatus. + */ +Size +BackendStatusShmemSize(void) +{ + Size size; + + /* BackendStatusArray: */ + size = mul_size(sizeof(PgBackendStatus), NumBackendStatSlots); + /* BackendAppnameBuffer: */ + size = add_size(size, + mul_size(NAMEDATALEN, NumBackendStatSlots)); + /* BackendClientHostnameBuffer: */ + size = add_size(size, + mul_size(NAMEDATALEN, NumBackendStatSlots)); + /* BackendActivityBuffer: */ + size = add_size(size, + mul_size(bestatus_track_activity_query_size, NumBackendStatSlots)); +#ifdef USE_SSL + /* BackendSslStatusBuffer: */ + size = add_size(size, + mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); +#endif + return size; +} + +/* + * Initialize the shared status array and several string buffers + * during postmaster startup. + */ +void +CreateSharedBackendStatus(void) +{ + Size size; + bool found; + int i; + char *buffer; + + /* Create or attach to the shared array */ + size = mul_size(sizeof(PgBackendStatus), NumBackendStatSlots); + BackendStatusArray = (PgBackendStatus *) + ShmemInitStruct("Backend Status Array", size, &found); + + if (!found) + { + /* + * We're the first - initialize. + */ + MemSet(BackendStatusArray, 0, size); + } + + /* Create or attach to the shared appname buffer */ + size = mul_size(NAMEDATALEN, NumBackendStatSlots); + BackendAppnameBuffer = (char *) + ShmemInitStruct("Backend Application Name Buffer", size, &found); + + if (!found) + { + MemSet(BackendAppnameBuffer, 0, size); + + /* Initialize st_appname pointers. */ + buffer = BackendAppnameBuffer; + for (i = 0; i < NumBackendStatSlots; i++) + { + BackendStatusArray[i].st_appname = buffer; + buffer += NAMEDATALEN; + } + } + + /* Create or attach to the shared client hostname buffer */ + size = mul_size(NAMEDATALEN, NumBackendStatSlots); + BackendClientHostnameBuffer = (char *) + ShmemInitStruct("Backend Client Host Name Buffer", size, &found); + + if (!found) + { + MemSet(BackendClientHostnameBuffer, 0, size); + + /* Initialize st_clienthostname pointers. */ + buffer = BackendClientHostnameBuffer; + for (i = 0; i < NumBackendStatSlots; i++) + { + BackendStatusArray[i].st_clienthostname = buffer; + buffer += NAMEDATALEN; + } + } + + /* Create or attach to the shared activity buffer */ + BackendActivityBufferSize = mul_size(bestatus_track_activity_query_size, + NumBackendStatSlots); + BackendActivityBuffer = (char *) + ShmemInitStruct("Backend Activity Buffer", + BackendActivityBufferSize, + &found); + + if (!found) + { + MemSet(BackendActivityBuffer, 0, BackendActivityBufferSize); + + /* Initialize st_activity pointers. */ + buffer = BackendActivityBuffer; + for (i = 0; i < NumBackendStatSlots; i++) + { + BackendStatusArray[i].st_activity_raw = buffer; + buffer += bestatus_track_activity_query_size; + } + } + +#ifdef USE_SSL + /* Create or attach to the shared SSL status buffer */ + size = mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots); + BackendSslStatusBuffer = (PgBackendSSLStatus *) + ShmemInitStruct("Backend SSL Status Buffer", size, &found); + + if (!found) + { + PgBackendSSLStatus *ptr; + + MemSet(BackendSslStatusBuffer, 0, size); + + /* Initialize st_sslstatus pointers. */ + ptr = BackendSslStatusBuffer; + for (i = 0; i < NumBackendStatSlots; i++) + { + BackendStatusArray[i].st_sslstatus = ptr; + ptr++; + } + } +#endif +} + +/* ---------- + * bestatus_initialize() - + * + * Initialize pgstats state, and set up our on-proc-exit hook. + * Called from InitPostgres and AuxiliaryProcessMain. For auxiliary process, + * MyBackendId is invalid. Otherwise, MyBackendId must be set, + * but we must not have started any transaction yet (since the + * exit hook must run after the last transaction exit). + * NOTE: MyDatabaseId isn't set yet; so the shutdown hook has to be careful. + * ---------- + */ +void +bestatus_initialize(void) +{ + /* Initialize MyBEEntry */ + if (MyBackendId != InvalidBackendId) + { + Assert(MyBackendId >= 1 && MyBackendId <= MaxBackends); + MyBEEntry = &BackendStatusArray[MyBackendId - 1]; + } + else + { + /* Must be an auxiliary process */ + Assert(MyAuxProcType != NotAnAuxProcess); + + /* + * Assign the MyBEEntry for an auxiliary process. Since it doesn't + * have a BackendId, the slot is statically allocated based on the + * auxiliary process type (MyAuxProcType). Backends use slots indexed + * in the range from 1 to MaxBackends (inclusive), so we use + * MaxBackends + AuxBackendType + 1 as the index of the slot for an + * auxiliary process. + */ + MyBEEntry = &BackendStatusArray[MaxBackends + MyAuxProcType]; + } + + /* Set up a process-exit hook to clean up */ + before_shmem_exit(bestatus_beshutdown_hook, 0); +} + +/* + * Shut down a single backend's statistics reporting at process exit. + * + * Flush any remaining statistics counts out to the collector. + * Without this, operations triggered during backend exit (such as + * temp table deletions) won't be counted. + * + * Lastly, clear out our entry in the PgBackendStatus array. + */ +static void +bestatus_beshutdown_hook(int code, Datum arg) +{ + volatile PgBackendStatus *beentry = MyBEEntry; + + /* + * Clear my status entry, following the protocol of bumping st_changecount + * before and after. We use a volatile pointer here to ensure the + * compiler doesn't try to get cute. + */ + bestatus_increment_changecount_before(beentry); + + beentry->st_procpid = 0; /* mark invalid */ + + bestatus_increment_changecount_after(beentry); +} + + +/* ---------- + * bestatus_bestart() - + * + * Initialize this backend's entry in the PgBackendStatus array. + * Called from InitPostgres. + * + * Apart from auxiliary processes, MyBackendId, MyDatabaseId, + * session userid, and application_name must be set for a + * backend (hence, this cannot be combined with bestatus_initialize). + * ---------- + */ +void +bestatus_bestart(void) +{ + SockAddr clientaddr; + volatile PgBackendStatus *beentry; + + /* + * To minimize the time spent modifying the PgBackendStatus entry, fetch + * all the needed data first. + */ + + /* + * We may not have a MyProcPort (eg, if this is the autovacuum process). + * If so, use all-zeroes client address, which is dealt with specially in + * pg_stat_get_backend_client_addr and pg_stat_get_backend_client_port. + */ + if (MyProcPort) + memcpy(&clientaddr, &MyProcPort->raddr, sizeof(clientaddr)); + else + MemSet(&clientaddr, 0, sizeof(clientaddr)); + + /* + * Initialize my status entry, following the protocol of bumping + * st_changecount before and after; and make sure it's even afterwards. We + * use a volatile pointer here to ensure the compiler doesn't try to get + * cute. + */ + beentry = MyBEEntry; + + /* pgstats state must be initialized from bestatus_initialize() */ + Assert(beentry != NULL); + + if (MyBackendId != InvalidBackendId) + { + if (IsAutoVacuumLauncherProcess()) + { + /* Autovacuum Launcher */ + beentry->st_backendType = B_AUTOVAC_LAUNCHER; + } + else if (IsAutoVacuumWorkerProcess()) + { + /* Autovacuum Worker */ + beentry->st_backendType = B_AUTOVAC_WORKER; + } + else if (am_walsender) + { + /* Wal sender */ + beentry->st_backendType = B_WAL_SENDER; + } + else if (IsBackgroundWorker) + { + /* bgworker */ + beentry->st_backendType = B_BG_WORKER; + } + else + { + /* client-backend */ + beentry->st_backendType = B_BACKEND; + } + } + else + { + /* Must be an auxiliary process */ + Assert(MyAuxProcType != NotAnAuxProcess); + switch (MyAuxProcType) + { + case StartupProcess: + beentry->st_backendType = B_STARTUP; + break; + case BgWriterProcess: + beentry->st_backendType = B_BG_WRITER; + break; + case CheckpointerProcess: + beentry->st_backendType = B_CHECKPOINTER; + break; + case WalWriterProcess: + beentry->st_backendType = B_WAL_WRITER; + break; + case WalReceiverProcess: + beentry->st_backendType = B_WAL_RECEIVER; + break; + case ArchiverProcess: + beentry->st_backendType = B_ARCHIVER; + break; + default: + elog(FATAL, "unrecognized process type: %d", + (int) MyAuxProcType); + proc_exit(1); + } + } + + do + { + bestatus_increment_changecount_before(beentry); + } while ((beentry->st_changecount & 1) == 0); + + beentry->st_procpid = MyProcPid; + beentry->st_proc_start_timestamp = MyStartTimestamp; + beentry->st_activity_start_timestamp = 0; + beentry->st_state_start_timestamp = 0; + beentry->st_xact_start_timestamp = 0; + beentry->st_databaseid = MyDatabaseId; + + /* We have userid for client-backends, wal-sender and bgworker processes */ + if (beentry->st_backendType == B_BACKEND + || beentry->st_backendType == B_WAL_SENDER + || beentry->st_backendType == B_BG_WORKER) + beentry->st_userid = GetSessionUserId(); + else + beentry->st_userid = InvalidOid; + + beentry->st_clientaddr = clientaddr; + if (MyProcPort && MyProcPort->remote_hostname) + strlcpy(beentry->st_clienthostname, MyProcPort->remote_hostname, + NAMEDATALEN); + else + beentry->st_clienthostname[0] = '\0'; +#ifdef USE_SSL + if (MyProcPort && MyProcPort->ssl != NULL) + { + beentry->st_ssl = true; + beentry->st_sslstatus->ssl_bits = be_tls_get_cipher_bits(MyProcPort); + beentry->st_sslstatus->ssl_compression = be_tls_get_compression(MyProcPort); + strlcpy(beentry->st_sslstatus->ssl_version, be_tls_get_version(MyProcPort), NAMEDATALEN); + strlcpy(beentry->st_sslstatus->ssl_cipher, be_tls_get_cipher(MyProcPort), NAMEDATALEN); + be_tls_get_peerdn_name(MyProcPort, beentry->st_sslstatus->ssl_clientdn, NAMEDATALEN); + } + else + { + beentry->st_ssl = false; + } +#else + beentry->st_ssl = false; +#endif + beentry->st_state = STATE_UNDEFINED; + beentry->st_appname[0] = '\0'; + beentry->st_activity_raw[0] = '\0'; + /* Also make sure the last byte in each string area is always 0 */ + beentry->st_clienthostname[NAMEDATALEN - 1] = '\0'; + beentry->st_appname[NAMEDATALEN - 1] = '\0'; + beentry->st_activity_raw[bestatus_track_activity_query_size - 1] = '\0'; + beentry->st_progress_command = PROGRESS_COMMAND_INVALID; + beentry->st_progress_command_target = InvalidOid; + + /* + * we don't zero st_progress_param here to save cycles; nobody should + * examine it until st_progress_command has been set to something other + * than PROGRESS_COMMAND_INVALID + */ + + bestatus_increment_changecount_after(beentry); + + /* Update app name to current GUC setting */ + if (application_name) + bestatus_report_appname(application_name); +} + +/* ---------- + * bestatus_read_current_status() - + * + * Copy the current contents of the PgBackendStatus array to local memory, + * if not already done in this transaction. + * ---------- + */ +static void +bestatus_read_current_status(void) +{ + volatile PgBackendStatus *beentry; + LocalPgBackendStatus *localtable; + LocalPgBackendStatus *localentry; + char *localappname, + *localclienthostname, + *localactivity; +#ifdef USE_SSL + PgBackendSSLStatus *localsslstatus; +#endif + int i; + + Assert(IsUnderPostmaster); + + if (localBackendStatusTable) + return; /* already done */ + + bestatus_setup_memcxt(); + + localtable = (LocalPgBackendStatus *) + MemoryContextAlloc(pgBeStatLocalContext, + sizeof(LocalPgBackendStatus) * NumBackendStatSlots); + localappname = (char *) + MemoryContextAlloc(pgBeStatLocalContext, + NAMEDATALEN * NumBackendStatSlots); + localclienthostname = (char *) + MemoryContextAlloc(pgBeStatLocalContext, + NAMEDATALEN * NumBackendStatSlots); + localactivity = (char *) + MemoryContextAlloc(pgBeStatLocalContext, + bestatus_track_activity_query_size * NumBackendStatSlots); +#ifdef USE_SSL + localsslstatus = (PgBackendSSLStatus *) + MemoryContextAlloc(pgBeStatLocalContext, + sizeof(PgBackendSSLStatus) * NumBackendStatSlots); +#endif + + localNumBackends = 0; + + beentry = BackendStatusArray; + localentry = localtable; + for (i = 1; i <= NumBackendStatSlots; i++) + { + /* + * Follow the protocol of retrying if st_changecount changes while we + * copy the entry, or if it's odd. (The check for odd is needed to + * cover the case where we are able to completely copy the entry while + * the source backend is between increment steps.) We use a volatile + * pointer here to ensure the compiler doesn't try to get cute. + */ + for (;;) + { + int before_changecount; + int after_changecount; + + bestatus_save_changecount_before(beentry, before_changecount); + + localentry->backendStatus.st_procpid = beentry->st_procpid; + if (localentry->backendStatus.st_procpid > 0) + { + memcpy(&localentry->backendStatus, (char *) beentry, sizeof(PgBackendStatus)); + + /* + * strcpy is safe even if the string is modified concurrently, + * because there's always a \0 at the end of the buffer. + */ + strcpy(localappname, (char *) beentry->st_appname); + localentry->backendStatus.st_appname = localappname; + strcpy(localclienthostname, (char *) beentry->st_clienthostname); + localentry->backendStatus.st_clienthostname = localclienthostname; + strcpy(localactivity, (char *) beentry->st_activity_raw); + localentry->backendStatus.st_activity_raw = localactivity; + localentry->backendStatus.st_ssl = beentry->st_ssl; +#ifdef USE_SSL + if (beentry->st_ssl) + { + memcpy(localsslstatus, beentry->st_sslstatus, sizeof(PgBackendSSLStatus)); + localentry->backendStatus.st_sslstatus = localsslstatus; + } +#endif + } + + bestatus_save_changecount_after(beentry, after_changecount); + if (before_changecount == after_changecount && + (before_changecount & 1) == 0) + break; + + /* Make sure we can break out of loop if stuck... */ + CHECK_FOR_INTERRUPTS(); + } + + beentry++; + /* Only valid entries get included into the local array */ + if (localentry->backendStatus.st_procpid > 0) + { + BackendIdGetTransactionIds(i, + &localentry->backend_xid, + &localentry->backend_xmin); + + localentry++; + localappname += NAMEDATALEN; + localclienthostname += NAMEDATALEN; + localactivity += bestatus_track_activity_query_size; +#ifdef USE_SSL + localsslstatus++; +#endif + localNumBackends++; + } + } + + /* Set the pointer only after completion of a valid table */ + localBackendStatusTable = localtable; +} + + +/* ---------- + * bestatus_fetch_stat_beentry() - + * + * Support function for the SQL-callable pgstat* functions. Returns + * our local copy of the current-activity entry for one backend. + * + * NB: caller is responsible for a check if the user is permitted to see + * this info (especially the querystring). + * ---------- + */ +PgBackendStatus * +bestatus_fetch_stat_beentry(int beid) +{ + bestatus_read_current_status(); + + if (beid < 1 || beid > localNumBackends) + return NULL; + + return &localBackendStatusTable[beid - 1].backendStatus; +} + + +/* ---------- + * bestatus_fetch_stat_local_beentry() - + * + * Like bestatus_fetch_stat_beentry() but with locally computed additions (like + * xid and xmin values of the backend) + * + * NB: caller is responsible for a check if the user is permitted to see + * this info (especially the querystring). + * ---------- + */ +LocalPgBackendStatus * +bestatus_fetch_stat_local_beentry(int beid) +{ + bestatus_read_current_status(); + + if (beid < 1 || beid > localNumBackends) + return NULL; + + return &localBackendStatusTable[beid - 1]; +} + + +/* ---------- + * bestatus_fetch_stat_numbackends() - + * + * Support function for the SQL-callable pgstat* functions. Returns + * the maximum current backend id. + * ---------- + */ +int +bestatus_fetch_stat_numbackends(void) +{ + bestatus_read_current_status(); + + return localNumBackends; +} + +/* ---------- + * bestatus_get_wait_event_type() - + * + * Return a string representing the current wait event type, backend is + * waiting on. + */ +const char * +bestatus_get_wait_event_type(uint32 wait_event_info) +{ + uint32 classId; + const char *event_type; + + /* report process as not waiting. */ + if (wait_event_info == 0) + return NULL; + + classId = wait_event_info & 0xFF000000; + + switch (classId) + { + case PG_WAIT_LWLOCK: + event_type = "LWLock"; + break; + case PG_WAIT_LOCK: + event_type = "Lock"; + break; + case PG_WAIT_BUFFER_PIN: + event_type = "BufferPin"; + break; + case PG_WAIT_ACTIVITY: + event_type = "Activity"; + break; + case PG_WAIT_CLIENT: + event_type = "Client"; + break; + case PG_WAIT_EXTENSION: + event_type = "Extension"; + break; + case PG_WAIT_IPC: + event_type = "IPC"; + break; + case PG_WAIT_TIMEOUT: + event_type = "Timeout"; + break; + case PG_WAIT_IO: + event_type = "IO"; + break; + default: + event_type = "???"; + break; + } + + return event_type; +} + +/* ---------- + * bestatus_get_wait_event() - + * + * Return a string representing the current wait event, backend is + * waiting on. + */ +const char * +bestatus_get_wait_event(uint32 wait_event_info) +{ + uint32 classId; + uint16 eventId; + const char *event_name; + + /* report process as not waiting. */ + if (wait_event_info == 0) + return NULL; + + classId = wait_event_info & 0xFF000000; + eventId = wait_event_info & 0x0000FFFF; + + switch (classId) + { + case PG_WAIT_LWLOCK: + event_name = GetLWLockIdentifier(classId, eventId); + break; + case PG_WAIT_LOCK: + event_name = GetLockNameFromTagType(eventId); + break; + case PG_WAIT_BUFFER_PIN: + event_name = "BufferPin"; + break; + case PG_WAIT_ACTIVITY: + { + WaitEventActivity w = (WaitEventActivity) wait_event_info; + + event_name = bestatus_get_wait_activity(w); + break; + } + case PG_WAIT_CLIENT: + { + WaitEventClient w = (WaitEventClient) wait_event_info; + + event_name = bestatus_get_wait_client(w); + break; + } + case PG_WAIT_EXTENSION: + event_name = "Extension"; + break; + case PG_WAIT_IPC: + { + WaitEventIPC w = (WaitEventIPC) wait_event_info; + + event_name = bestatus_get_wait_ipc(w); + break; + } + case PG_WAIT_TIMEOUT: + { + WaitEventTimeout w = (WaitEventTimeout) wait_event_info; + + event_name = bestatus_get_wait_timeout(w); + break; + } + case PG_WAIT_IO: + { + WaitEventIO w = (WaitEventIO) wait_event_info; + + event_name = bestatus_get_wait_io(w); + break; + } + default: + event_name = "unknown wait event"; + break; + } + + return event_name; +} + +/* ---------- + * bestatus_get_wait_activity() - + * + * Convert WaitEventActivity to string. + * ---------- + */ +static const char * +bestatus_get_wait_activity(WaitEventActivity w) +{ + const char *event_name = "unknown wait event"; + + switch (w) + { + case WAIT_EVENT_ARCHIVER_MAIN: + event_name = "ArchiverMain"; + break; + case WAIT_EVENT_AUTOVACUUM_MAIN: + event_name = "AutoVacuumMain"; + break; + case WAIT_EVENT_BGWRITER_HIBERNATE: + event_name = "BgWriterHibernate"; + break; + case WAIT_EVENT_BGWRITER_MAIN: + event_name = "BgWriterMain"; + break; + case WAIT_EVENT_CHECKPOINTER_MAIN: + event_name = "CheckpointerMain"; + break; + case WAIT_EVENT_LOGICAL_APPLY_MAIN: + event_name = "LogicalApplyMain"; + break; + case WAIT_EVENT_LOGICAL_LAUNCHER_MAIN: + event_name = "LogicalLauncherMain"; + break; + case WAIT_EVENT_BESTATUS_MAIN: + event_name = "PgStatMain"; + break; + case WAIT_EVENT_RECOVERY_WAL_ALL: + event_name = "RecoveryWalAll"; + break; + case WAIT_EVENT_RECOVERY_WAL_STREAM: + event_name = "RecoveryWalStream"; + break; + case WAIT_EVENT_SYSLOGGER_MAIN: + event_name = "SysLoggerMain"; + break; + case WAIT_EVENT_WAL_RECEIVER_MAIN: + event_name = "WalReceiverMain"; + break; + case WAIT_EVENT_WAL_SENDER_MAIN: + event_name = "WalSenderMain"; + break; + case WAIT_EVENT_WAL_WRITER_MAIN: + event_name = "WalWriterMain"; + break; + /* no default case, so that compiler will warn */ + } + + return event_name; +} + +/* ---------- + * bestatus_get_wait_client() - + * + * Convert WaitEventClient to string. + * ---------- + */ +static const char * +bestatus_get_wait_client(WaitEventClient w) +{ + const char *event_name = "unknown wait event"; + + switch (w) + { + case WAIT_EVENT_CLIENT_READ: + event_name = "ClientRead"; + break; + case WAIT_EVENT_CLIENT_WRITE: + event_name = "ClientWrite"; + break; + case WAIT_EVENT_LIBPQWALRECEIVER_CONNECT: + event_name = "LibPQWalReceiverConnect"; + break; + case WAIT_EVENT_LIBPQWALRECEIVER_RECEIVE: + event_name = "LibPQWalReceiverReceive"; + break; + case WAIT_EVENT_SSL_OPEN_SERVER: + event_name = "SSLOpenServer"; + break; + case WAIT_EVENT_WAL_RECEIVER_WAIT_START: + event_name = "WalReceiverWaitStart"; + break; + case WAIT_EVENT_WAL_SENDER_WAIT_WAL: + event_name = "WalSenderWaitForWAL"; + break; + case WAIT_EVENT_WAL_SENDER_WRITE_DATA: + event_name = "WalSenderWriteData"; + break; + /* no default case, so that compiler will warn */ + } + + return event_name; +} + +/* ---------- + * bestatus_get_wait_ipc() - + * + * Convert WaitEventIPC to string. + * ---------- + */ +static const char * +bestatus_get_wait_ipc(WaitEventIPC w) +{ + const char *event_name = "unknown wait event"; + + switch (w) + { + case WAIT_EVENT_BGWORKER_SHUTDOWN: + event_name = "BgWorkerShutdown"; + break; + case WAIT_EVENT_BGWORKER_STARTUP: + event_name = "BgWorkerStartup"; + break; + case WAIT_EVENT_BTREE_PAGE: + event_name = "BtreePage"; + break; + case WAIT_EVENT_CLOG_GROUP_UPDATE: + event_name = "ClogGroupUpdate"; + break; + case WAIT_EVENT_EXECUTE_GATHER: + event_name = "ExecuteGather"; + break; + case WAIT_EVENT_HASH_BATCH_ALLOCATING: + event_name = "Hash/Batch/Allocating"; + break; + case WAIT_EVENT_HASH_BATCH_ELECTING: + event_name = "Hash/Batch/Electing"; + break; + case WAIT_EVENT_HASH_BATCH_LOADING: + event_name = "Hash/Batch/Loading"; + break; + case WAIT_EVENT_HASH_BUILD_ALLOCATING: + event_name = "Hash/Build/Allocating"; + break; + case WAIT_EVENT_HASH_BUILD_ELECTING: + event_name = "Hash/Build/Electing"; + break; + case WAIT_EVENT_HASH_BUILD_HASHING_INNER: + event_name = "Hash/Build/HashingInner"; + break; + case WAIT_EVENT_HASH_BUILD_HASHING_OUTER: + event_name = "Hash/Build/HashingOuter"; + break; + case WAIT_EVENT_HASH_GROW_BATCHES_ALLOCATING: + event_name = "Hash/GrowBatches/Allocating"; + break; + case WAIT_EVENT_HASH_GROW_BATCHES_DECIDING: + event_name = "Hash/GrowBatches/Deciding"; + break; + case WAIT_EVENT_HASH_GROW_BATCHES_ELECTING: + event_name = "Hash/GrowBatches/Electing"; + break; + case WAIT_EVENT_HASH_GROW_BATCHES_FINISHING: + event_name = "Hash/GrowBatches/Finishing"; + break; + case WAIT_EVENT_HASH_GROW_BATCHES_REPARTITIONING: + event_name = "Hash/GrowBatches/Repartitioning"; + break; + case WAIT_EVENT_HASH_GROW_BUCKETS_ALLOCATING: + event_name = "Hash/GrowBuckets/Allocating"; + break; + case WAIT_EVENT_HASH_GROW_BUCKETS_ELECTING: + event_name = "Hash/GrowBuckets/Electing"; + break; + case WAIT_EVENT_HASH_GROW_BUCKETS_REINSERTING: + event_name = "Hash/GrowBuckets/Reinserting"; + break; + case WAIT_EVENT_LOGICAL_SYNC_DATA: + event_name = "LogicalSyncData"; + break; + case WAIT_EVENT_LOGICAL_SYNC_STATE_CHANGE: + event_name = "LogicalSyncStateChange"; + break; + case WAIT_EVENT_MQ_INTERNAL: + event_name = "MessageQueueInternal"; + break; + case WAIT_EVENT_MQ_PUT_MESSAGE: + event_name = "MessageQueuePutMessage"; + break; + case WAIT_EVENT_MQ_RECEIVE: + event_name = "MessageQueueReceive"; + break; + case WAIT_EVENT_MQ_SEND: + event_name = "MessageQueueSend"; + break; + case WAIT_EVENT_PARALLEL_BITMAP_SCAN: + event_name = "ParallelBitmapScan"; + break; + case WAIT_EVENT_PARALLEL_CREATE_INDEX_SCAN: + event_name = "ParallelCreateIndexScan"; + break; + case WAIT_EVENT_PARALLEL_FINISH: + event_name = "ParallelFinish"; + break; + case WAIT_EVENT_PROCARRAY_GROUP_UPDATE: + event_name = "ProcArrayGroupUpdate"; + break; + case WAIT_EVENT_PROMOTE: + event_name = "Promote"; + break; + case WAIT_EVENT_REPLICATION_ORIGIN_DROP: + event_name = "ReplicationOriginDrop"; + break; + case WAIT_EVENT_REPLICATION_SLOT_DROP: + event_name = "ReplicationSlotDrop"; + break; + case WAIT_EVENT_SAFE_SNAPSHOT: + event_name = "SafeSnapshot"; + break; + case WAIT_EVENT_SYNC_REP: + event_name = "SyncRep"; + break; + /* no default case, so that compiler will warn */ + } + + return event_name; +} + +/* ---------- + * bestatus_get_wait_timeout() - + * + * Convert WaitEventTimeout to string. + * ---------- + */ +static const char * +bestatus_get_wait_timeout(WaitEventTimeout w) +{ + const char *event_name = "unknown wait event"; + + switch (w) + { + case WAIT_EVENT_BASE_BACKUP_THROTTLE: + event_name = "BaseBackupThrottle"; + break; + case WAIT_EVENT_PG_SLEEP: + event_name = "PgSleep"; + break; + case WAIT_EVENT_RECOVERY_APPLY_DELAY: + event_name = "RecoveryApplyDelay"; + break; + /* no default case, so that compiler will warn */ + } + + return event_name; +} + +/* ---------- + * bestatus_get_wait_io() - + * + * Convert WaitEventIO to string. + * ---------- + */ +static const char * +bestatus_get_wait_io(WaitEventIO w) +{ + const char *event_name = "unknown wait event"; + + switch (w) + { + case WAIT_EVENT_BUFFILE_READ: + event_name = "BufFileRead"; + break; + case WAIT_EVENT_BUFFILE_WRITE: + event_name = "BufFileWrite"; + break; + case WAIT_EVENT_CONTROL_FILE_READ: + event_name = "ControlFileRead"; + break; + case WAIT_EVENT_CONTROL_FILE_SYNC: + event_name = "ControlFileSync"; + break; + case WAIT_EVENT_CONTROL_FILE_SYNC_UPDATE: + event_name = "ControlFileSyncUpdate"; + break; + case WAIT_EVENT_CONTROL_FILE_WRITE: + event_name = "ControlFileWrite"; + break; + case WAIT_EVENT_CONTROL_FILE_WRITE_UPDATE: + event_name = "ControlFileWriteUpdate"; + break; + case WAIT_EVENT_COPY_FILE_READ: + event_name = "CopyFileRead"; + break; + case WAIT_EVENT_COPY_FILE_WRITE: + event_name = "CopyFileWrite"; + break; + case WAIT_EVENT_DATA_FILE_EXTEND: + event_name = "DataFileExtend"; + break; + case WAIT_EVENT_DATA_FILE_FLUSH: + event_name = "DataFileFlush"; + break; + case WAIT_EVENT_DATA_FILE_IMMEDIATE_SYNC: + event_name = "DataFileImmediateSync"; + break; + case WAIT_EVENT_DATA_FILE_PREFETCH: + event_name = "DataFilePrefetch"; + break; + case WAIT_EVENT_DATA_FILE_READ: + event_name = "DataFileRead"; + break; + case WAIT_EVENT_DATA_FILE_SYNC: + event_name = "DataFileSync"; + break; + case WAIT_EVENT_DATA_FILE_TRUNCATE: + event_name = "DataFileTruncate"; + break; + case WAIT_EVENT_DATA_FILE_WRITE: + event_name = "DataFileWrite"; + break; + case WAIT_EVENT_DSM_FILL_ZERO_WRITE: + event_name = "DSMFillZeroWrite"; + break; + case WAIT_EVENT_LOCK_FILE_ADDTODATADIR_READ: + event_name = "LockFileAddToDataDirRead"; + break; + case WAIT_EVENT_LOCK_FILE_ADDTODATADIR_SYNC: + event_name = "LockFileAddToDataDirSync"; + break; + case WAIT_EVENT_LOCK_FILE_ADDTODATADIR_WRITE: + event_name = "LockFileAddToDataDirWrite"; + break; + case WAIT_EVENT_LOCK_FILE_CREATE_READ: + event_name = "LockFileCreateRead"; + break; + case WAIT_EVENT_LOCK_FILE_CREATE_SYNC: + event_name = "LockFileCreateSync"; + break; + case WAIT_EVENT_LOCK_FILE_CREATE_WRITE: + event_name = "LockFileCreateWRITE"; + break; + case WAIT_EVENT_LOCK_FILE_RECHECKDATADIR_READ: + event_name = "LockFileReCheckDataDirRead"; + break; + case WAIT_EVENT_LOGICAL_REWRITE_CHECKPOINT_SYNC: + event_name = "LogicalRewriteCheckpointSync"; + break; + case WAIT_EVENT_LOGICAL_REWRITE_MAPPING_SYNC: + event_name = "LogicalRewriteMappingSync"; + break; + case WAIT_EVENT_LOGICAL_REWRITE_MAPPING_WRITE: + event_name = "LogicalRewriteMappingWrite"; + break; + case WAIT_EVENT_LOGICAL_REWRITE_SYNC: + event_name = "LogicalRewriteSync"; + break; + case WAIT_EVENT_LOGICAL_REWRITE_TRUNCATE: + event_name = "LogicalRewriteTruncate"; + break; + case WAIT_EVENT_LOGICAL_REWRITE_WRITE: + event_name = "LogicalRewriteWrite"; + break; + case WAIT_EVENT_RELATION_MAP_READ: + event_name = "RelationMapRead"; + break; + case WAIT_EVENT_RELATION_MAP_SYNC: + event_name = "RelationMapSync"; + break; + case WAIT_EVENT_RELATION_MAP_WRITE: + event_name = "RelationMapWrite"; + break; + case WAIT_EVENT_REORDER_BUFFER_READ: + event_name = "ReorderBufferRead"; + break; + case WAIT_EVENT_REORDER_BUFFER_WRITE: + event_name = "ReorderBufferWrite"; + break; + case WAIT_EVENT_REORDER_LOGICAL_MAPPING_READ: + event_name = "ReorderLogicalMappingRead"; + break; + case WAIT_EVENT_REPLICATION_SLOT_READ: + event_name = "ReplicationSlotRead"; + break; + case WAIT_EVENT_REPLICATION_SLOT_RESTORE_SYNC: + event_name = "ReplicationSlotRestoreSync"; + break; + case WAIT_EVENT_REPLICATION_SLOT_SYNC: + event_name = "ReplicationSlotSync"; + break; + case WAIT_EVENT_REPLICATION_SLOT_WRITE: + event_name = "ReplicationSlotWrite"; + break; + case WAIT_EVENT_SLRU_FLUSH_SYNC: + event_name = "SLRUFlushSync"; + break; + case WAIT_EVENT_SLRU_READ: + event_name = "SLRURead"; + break; + case WAIT_EVENT_SLRU_SYNC: + event_name = "SLRUSync"; + break; + case WAIT_EVENT_SLRU_WRITE: + event_name = "SLRUWrite"; + break; + case WAIT_EVENT_SNAPBUILD_READ: + event_name = "SnapbuildRead"; + break; + case WAIT_EVENT_SNAPBUILD_SYNC: + event_name = "SnapbuildSync"; + break; + case WAIT_EVENT_SNAPBUILD_WRITE: + event_name = "SnapbuildWrite"; + break; + case WAIT_EVENT_TIMELINE_HISTORY_FILE_SYNC: + event_name = "TimelineHistoryFileSync"; + break; + case WAIT_EVENT_TIMELINE_HISTORY_FILE_WRITE: + event_name = "TimelineHistoryFileWrite"; + break; + case WAIT_EVENT_TIMELINE_HISTORY_READ: + event_name = "TimelineHistoryRead"; + break; + case WAIT_EVENT_TIMELINE_HISTORY_SYNC: + event_name = "TimelineHistorySync"; + break; + case WAIT_EVENT_TIMELINE_HISTORY_WRITE: + event_name = "TimelineHistoryWrite"; + break; + case WAIT_EVENT_TWOPHASE_FILE_READ: + event_name = "TwophaseFileRead"; + break; + case WAIT_EVENT_TWOPHASE_FILE_SYNC: + event_name = "TwophaseFileSync"; + break; + case WAIT_EVENT_TWOPHASE_FILE_WRITE: + event_name = "TwophaseFileWrite"; + break; + case WAIT_EVENT_WALSENDER_TIMELINE_HISTORY_READ: + event_name = "WALSenderTimelineHistoryRead"; + break; + case WAIT_EVENT_WAL_BOOTSTRAP_SYNC: + event_name = "WALBootstrapSync"; + break; + case WAIT_EVENT_WAL_BOOTSTRAP_WRITE: + event_name = "WALBootstrapWrite"; + break; + case WAIT_EVENT_WAL_COPY_READ: + event_name = "WALCopyRead"; + break; + case WAIT_EVENT_WAL_COPY_SYNC: + event_name = "WALCopySync"; + break; + case WAIT_EVENT_WAL_COPY_WRITE: + event_name = "WALCopyWrite"; + break; + case WAIT_EVENT_WAL_INIT_SYNC: + event_name = "WALInitSync"; + break; + case WAIT_EVENT_WAL_INIT_WRITE: + event_name = "WALInitWrite"; + break; + case WAIT_EVENT_WAL_READ: + event_name = "WALRead"; + break; + case WAIT_EVENT_WAL_SYNC: + event_name = "WALSync"; + break; + case WAIT_EVENT_WAL_SYNC_METHOD_ASSIGN: + event_name = "WALSyncMethodAssign"; + break; + case WAIT_EVENT_WAL_WRITE: + event_name = "WALWrite"; + break; + + /* no default case, so that compiler will warn */ + } + + return event_name; +} + + +/* ---------- + * bestatus_get_backend_current_activity() - + * + * Return a string representing the current activity of the backend with + * the specified PID. This looks directly at the BackendStatusArray, + * and so will provide current information regardless of the age of our + * transaction's snapshot of the status array. + * + * It is the caller's responsibility to invoke this only for backends whose + * state is expected to remain stable while the result is in use. The + * only current use is in deadlock reporting, where we can expect that + * the target backend is blocked on a lock. (There are corner cases + * where the target's wait could get aborted while we are looking at it, + * but the very worst consequence is to return a pointer to a string + * that's been changed, so we won't worry too much.) + * + * Note: return strings for special cases match pg_stat_get_backend_activity. + * ---------- + */ +const char * +bestatus_get_backend_current_activity(int pid, bool checkUser) +{ + PgBackendStatus *beentry; + int i; + + beentry = BackendStatusArray; + for (i = 1; i <= MaxBackends; i++) + { + /* + * Although we expect the target backend's entry to be stable, that + * doesn't imply that anyone else's is. To avoid identifying the + * wrong backend, while we check for a match to the desired PID we + * must follow the protocol of retrying if st_changecount changes + * while we examine the entry, or if it's odd. (This might be + * unnecessary, since fetching or storing an int is almost certainly + * atomic, but let's play it safe.) We use a volatile pointer here to + * ensure the compiler doesn't try to get cute. + */ + volatile PgBackendStatus *vbeentry = beentry; + bool found; + + for (;;) + { + int before_changecount; + int after_changecount; + + bestatus_save_changecount_before(vbeentry, before_changecount); + + found = (vbeentry->st_procpid == pid); + + bestatus_save_changecount_after(vbeentry, after_changecount); + + if (before_changecount == after_changecount && + (before_changecount & 1) == 0) + break; + + /* Make sure we can break out of loop if stuck... */ + CHECK_FOR_INTERRUPTS(); + } + + if (found) + { + /* Now it is safe to use the non-volatile pointer */ + if (checkUser && !superuser() && beentry->st_userid != GetUserId()) + return ""; + else if (*(beentry->st_activity_raw) == '\0') + return ""; + else + { + /* this'll leak a bit of memory, but that seems acceptable */ + return bestatus_clip_activity(beentry->st_activity_raw); + } + } + + beentry++; + } + + /* If we get here, caller is in error ... */ + return ""; +} + +/* ---------- + * bestatus_get_crashed_backend_activity() - + * + * Return a string representing the current activity of the backend with + * the specified PID. Like the function above, but reads shared memory with + * the expectation that it may be corrupt. On success, copy the string + * into the "buffer" argument and return that pointer. On failure, + * return NULL. + * + * This function is only intended to be used by the postmaster to report the + * query that crashed a backend. In particular, no attempt is made to + * follow the correct concurrency protocol when accessing the + * BackendStatusArray. But that's OK, in the worst case we'll return a + * corrupted message. We also must take care not to trip on ereport(ERROR). + * ---------- + */ +const char * +bestatus_get_crashed_backend_activity(int pid, char *buffer, int buflen) +{ + volatile PgBackendStatus *beentry; + int i; + + beentry = BackendStatusArray; + + /* + * We probably shouldn't get here before shared memory has been set up, + * but be safe. + */ + if (beentry == NULL || BackendActivityBuffer == NULL) + return NULL; + + for (i = 1; i <= MaxBackends; i++) + { + if (beentry->st_procpid == pid) + { + /* Read pointer just once, so it can't change after validation */ + const char *activity = beentry->st_activity_raw; + const char *activity_last; + + /* + * We mustn't access activity string before we verify that it + * falls within the BackendActivityBuffer. To make sure that the + * entire string including its ending is contained within the + * buffer, subtract one activity length from the buffer size. + */ + activity_last = BackendActivityBuffer + BackendActivityBufferSize + - bestatus_track_activity_query_size; + + if (activity < BackendActivityBuffer || + activity > activity_last) + return NULL; + + /* If no string available, no point in a report */ + if (activity[0] == '\0') + return NULL; + + /* + * Copy only ASCII-safe characters so we don't run into encoding + * problems when reporting the message; and be sure not to run off + * the end of memory. As only ASCII characters are reported, it + * doesn't seem necessary to perform multibyte aware clipping. + */ + ascii_safe_strlcpy(buffer, activity, + Min(buflen, bestatus_track_activity_query_size)); + + return buffer; + } + + beentry++; + } + + /* PID not found */ + return NULL; +} + +const char * +bestatus_get_backend_desc(BackendType backendType) +{ + const char *backendDesc = "unknown process type"; + + switch (backendType) + { + case B_AUTOVAC_LAUNCHER: + backendDesc = "autovacuum launcher"; + break; + case B_AUTOVAC_WORKER: + backendDesc = "autovacuum worker"; + break; + case B_BACKEND: + backendDesc = "client backend"; + break; + case B_BG_WORKER: + backendDesc = "background worker"; + break; + case B_BG_WRITER: + backendDesc = "background writer"; + break; + case B_CHECKPOINTER: + backendDesc = "checkpointer"; + break; + case B_STARTUP: + backendDesc = "startup"; + break; + case B_WAL_RECEIVER: + backendDesc = "walreceiver"; + break; + case B_WAL_SENDER: + backendDesc = "walsender"; + break; + case B_WAL_WRITER: + backendDesc = "walwriter"; + break; + case B_ARCHIVER: + backendDesc = "archiver"; + break; + } + + return backendDesc; +} + +/* ---------- + * bestatus_report_appname() - + * + * Called to update our application name. + * ---------- + */ +void +bestatus_report_appname(const char *appname) +{ + volatile PgBackendStatus *beentry = MyBEEntry; + int len; + + if (!beentry) + return; + + /* This should be unnecessary if GUC did its job, but be safe */ + len = pg_mbcliplen(appname, strlen(appname), NAMEDATALEN - 1); + + /* + * Update my status entry, following the protocol of bumping + * st_changecount before and after. We use a volatile pointer here to + * ensure the compiler doesn't try to get cute. + */ + bestatus_increment_changecount_before(beentry); + + memcpy((char *) beentry->st_appname, appname, len); + beentry->st_appname[len] = '\0'; + + bestatus_increment_changecount_after(beentry); +} + +/* + * Report current transaction start timestamp as the specified value. + * Zero means there is no active transaction. + */ +void +bestatus_report_xact_timestamp(TimestampTz tstamp) +{ + volatile PgBackendStatus *beentry = MyBEEntry; + + if (!bestatus_track_activities || !beentry) + return; + + /* + * Update my status entry, following the protocol of bumping + * st_changecount before and after. We use a volatile pointer here to + * ensure the compiler doesn't try to get cute. + */ + bestatus_increment_changecount_before(beentry); + beentry->st_xact_start_timestamp = tstamp; + bestatus_increment_changecount_after(beentry); +} + +/* ---------- + * bestatus_setup_memcxt() - + * + * Create pgBeStatLocalContext, if not already done. + * ---------- + */ +static void +bestatus_setup_memcxt(void) +{ + if (!pgBeStatLocalContext) + pgBeStatLocalContext = AllocSetContextCreate(TopMemoryContext, + "Backend status snapshot", + ALLOCSET_SMALL_SIZES); +} + +/* ---------- + * bestatus_clear_snapshot() - + * + * Discard any data collected in the current transaction. Any subsequent + * request will cause new snapshots to be read. + * + * This is also invoked during transaction commit or abort to discard + * the no-longer-wanted snapshot. + * ---------- + */ +void +bestatus_clear_snapshot(void) +{ + /* Release memory, if any was allocated */ + if (pgBeStatLocalContext) + MemoryContextDelete(pgBeStatLocalContext); + + /* Reset variables */ + pgBeStatLocalContext = NULL; + localBackendStatusTable = NULL; + localNumBackends = 0; +} + + + +/* ---------- + * bestatus_report_activity() - + * + * Called from tcop/postgres.c to report what the backend is actually doing + * (but note cmd_str can be NULL for certain cases). + * + * All updates of the status entry follow the protocol of bumping + * st_changecount before and after. We use a volatile pointer here to + * ensure the compiler doesn't try to get cute. + * ---------- + */ +void +bestatus_report_activity(BackendState state, const char *cmd_str) +{ + volatile PgBackendStatus *beentry = MyBEEntry; + TimestampTz start_timestamp; + TimestampTz current_timestamp; + int len = 0; + + TRACE_POSTGRESQL_STATEMENT_STATUS(cmd_str); + + if (!beentry) + return; + + if (!bestatus_track_activities) + { + if (beentry->st_state != STATE_DISABLED) + { + volatile PGPROC *proc = MyProc; + + /* + * track_activities is disabled, but we last reported a + * non-disabled state. As our final update, change the state and + * clear fields we will not be updating anymore. + */ + bestatus_increment_changecount_before(beentry); + beentry->st_state = STATE_DISABLED; + beentry->st_state_start_timestamp = 0; + beentry->st_activity_raw[0] = '\0'; + beentry->st_activity_start_timestamp = 0; + /* st_xact_start_timestamp and wait_event_info are also disabled */ + beentry->st_xact_start_timestamp = 0; + proc->wait_event_info = 0; + bestatus_increment_changecount_after(beentry); + } + return; + } + + /* + * To minimize the time spent modifying the entry, fetch all the needed + * data first. + */ + start_timestamp = GetCurrentStatementStartTimestamp(); + if (cmd_str != NULL) + { + /* + * Compute length of to-be-stored string unaware of multi-byte + * characters. For speed reasons that'll get corrected on read, rather + * than computed every write. + */ + len = Min(strlen(cmd_str), bestatus_track_activity_query_size - 1); + } + current_timestamp = GetCurrentTimestamp(); + + /* + * Now update the status entry + */ + bestatus_increment_changecount_before(beentry); + + beentry->st_state = state; + beentry->st_state_start_timestamp = current_timestamp; + + if (cmd_str != NULL) + { + memcpy((char *) beentry->st_activity_raw, cmd_str, len); + beentry->st_activity_raw[len] = '\0'; + beentry->st_activity_start_timestamp = start_timestamp; + } + + bestatus_increment_changecount_after(beentry); +} + +/*----------- + * bestatus_progress_start_command() - + * + * Set st_progress_command (and st_progress_command_target) in own backend + * entry. Also, zero-initialize st_progress_param array. + *----------- + */ +void +bestatus_progress_start_command(ProgressCommandType cmdtype, Oid relid) +{ + volatile PgBackendStatus *beentry = MyBEEntry; + + if (!beentry || !bestatus_track_activities) + return; + + bestatus_increment_changecount_before(beentry); + beentry->st_progress_command = cmdtype; + beentry->st_progress_command_target = relid; + MemSet(&beentry->st_progress_param, 0, sizeof(beentry->st_progress_param)); + bestatus_increment_changecount_after(beentry); +} + +/*----------- + * bestatus_progress_update_param() - + * + * Update index'th member in st_progress_param[] of own backend entry. + *----------- + */ +void +bestatus_progress_update_param(int index, int64 val) +{ + volatile PgBackendStatus *beentry = MyBEEntry; + + Assert(index >= 0 && index < BESTATUS_NUM_PROGRESS_PARAM); + + if (!beentry || !bestatus_track_activities) + return; + + bestatus_increment_changecount_before(beentry); + beentry->st_progress_param[index] = val; + bestatus_increment_changecount_after(beentry); +} + +/*----------- + * bestatus_progress_update_multi_param() - + * + * Update multiple members in st_progress_param[] of own backend entry. + * This is atomic; readers won't see intermediate states. + *----------- + */ +void +bestatus_progress_update_multi_param(int nparam, const int *index, + const int64 *val) +{ + volatile PgBackendStatus *beentry = MyBEEntry; + int i; + + if (!beentry || !bestatus_track_activities || nparam == 0) + return; + + bestatus_increment_changecount_before(beentry); + + for (i = 0; i < nparam; ++i) + { + Assert(index[i] >= 0 && index[i] < BESTATUS_NUM_PROGRESS_PARAM); + + beentry->st_progress_param[index[i]] = val[i]; + } + + bestatus_increment_changecount_after(beentry); +} + +/*----------- + * bestatus_progress_end_command() - + * + * Reset st_progress_command (and st_progress_command_target) in own backend + * entry. This signals the end of the command. + *----------- + */ +void +bestatus_progress_end_command(void) +{ + volatile PgBackendStatus *beentry = MyBEEntry; + + if (!beentry) + return; + if (!bestatus_track_activities + && beentry->st_progress_command == PROGRESS_COMMAND_INVALID) + return; + + bestatus_increment_changecount_before(beentry); + beentry->st_progress_command = PROGRESS_COMMAND_INVALID; + beentry->st_progress_command_target = InvalidOid; + bestatus_increment_changecount_after(beentry); +} + + +/* + * Convert a potentially unsafely truncated activity string (see + * PgBackendStatus.st_activity_raw's documentation) into a correctly truncated + * one. + * + * The returned string is allocated in the caller's memory context and may be + * freed. + */ +char * +bestatus_clip_activity(const char *raw_activity) +{ + char *activity; + int rawlen; + int cliplen; + + /* + * Some callers, like bestatus_get_backend_current_activity(), do not + * guarantee that the buffer isn't concurrently modified. We try to take + * care that the buffer is always terminated by a NUL byte regardless, but + * let's still be paranoid about the string's length. In those cases the + * underlying buffer is guaranteed to be bestatus_track_activity_query_size + * large. + */ + activity = pnstrdup(raw_activity, bestatus_track_activity_query_size - 1); + + /* now double-guaranteed to be NUL terminated */ + rawlen = strlen(activity); + + /* + * All supported server-encodings make it possible to determine the length + * of a multi-byte character from its first byte (this is not the case for + * client encodings, see GB18030). As st_activity is always stored using + * server encoding, this allows us to perform multi-byte aware truncation, + * even if the string earlier was truncated in the middle of a multi-byte + * character. + */ + cliplen = pg_mbcliplen(activity, rawlen, + bestatus_track_activity_query_size - 1); + + activity[cliplen] = '\0'; + + return activity; +} diff --git a/src/backend/postmaster/pgstat.c b/src/backend/statmon/pgstat.c similarity index 70% rename from src/backend/postmaster/pgstat.c rename to src/backend/statmon/pgstat.c index 2d3f7cb898..df7995fb74 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/statmon/pgstat.c @@ -8,7 +8,7 @@ * * Copyright (c) 2001-2018, PostgreSQL Global Development Group * - * src/backend/postmaster/pgstat.c + * src/backend/statmon/pgstat.c * ---------- */ #include "postgres.h" @@ -21,19 +21,14 @@ #include "access/htup_details.h" #include "access/twophase_rmgr.h" #include "access/xact.h" +#include "bestatus.h" #include "catalog/pg_database.h" #include "catalog/pg_proc.h" -#include "libpq/libpq.h" #include "miscadmin.h" -#include "pg_trace.h" #include "postmaster/autovacuum.h" -#include "replication/walsender.h" #include "storage/ipc.h" #include "storage/lmgr.h" #include "storage/procsignal.h" -#include "storage/sinvaladt.h" -#include "utils/ascii.h" -#include "utils/guc.h" #include "utils/memutils.h" #include "utils/snapmgr.h" @@ -68,26 +63,12 @@ typedef enum PGSTAT_ENTRY_LOCK_FAILED } pg_stat_table_result_status; -/* ---------- - * Total number of backends including auxiliary - * - * We reserve a slot for each possible BackendId, plus one for each - * possible auxiliary process type. (This scheme assumes there is not - * more than one of any auxiliary process type at a time.) MaxBackends - * includes autovacuum workers and background workers as well. - * ---------- - */ -#define NumBackendStatSlots (MaxBackends + NUM_AUXPROCTYPES) - - /* ---------- * GUC parameters * ---------- */ -bool pgstat_track_activities = false; bool pgstat_track_counts = false; int pgstat_track_functions = TRACK_FUNC_OFF; -int pgstat_track_activity_query_size = 1024; /* Shared stats bootstrap infomation */ typedef struct StatsShmemStruct { @@ -125,6 +106,8 @@ static bool pgstat_pending_recoveryconflict = false; static bool pgstat_pending_deadlock = false; static bool pgstat_pending_tempfile = false; +static MemoryContext pgStatLocalContext = NULL; + /* dshash parameter for each type of table */ static const dshash_parameters dsh_dbparams = { sizeof(Oid), @@ -236,15 +219,8 @@ typedef struct /* * Info about current "snapshot" of stats file */ -static MemoryContext pgStatLocalContext = NULL; static HTAB *pgStatDBHash = NULL; -/* Status for backends including auxiliary */ -static LocalPgBackendStatus *localBackendStatusTable = NULL; - -/* Total number of backends including auxiliary */ -static int localNumBackends = 0; - /* * Cluster wide statistics. * Contains statistics that are not collected per database or per table. @@ -280,7 +256,6 @@ static void pgstat_read_db_statsfile(Oid databaseid, dshash_table *tabhash, dsha /* functions used in backends */ static bool backend_snapshot_global_stats(void); static PgStat_StatFuncEntry *backend_get_func_etnry(PgStat_StatDBEntry *dbent, Oid funcid, bool oneshot); -static void pgstat_read_current_status(void); static void pgstat_postmaster_shutdown(int code, Datum arg); static void pgstat_apply_pending_tabstats(bool shared, bool force, @@ -307,12 +282,6 @@ static PgStat_TableStatus *get_tabstat_entry(Oid rel_id, bool isshared); static void pgstat_setup_memcxt(void); -static const char *pgstat_get_wait_activity(WaitEventActivity w); -static const char *pgstat_get_wait_client(WaitEventClient w); -static const char *pgstat_get_wait_ipc(WaitEventIPC w); -static const char *pgstat_get_wait_timeout(WaitEventTimeout w); -static const char *pgstat_get_wait_io(WaitEventIO w); - static bool pgstat_update_tabentry(dshash_table *tabhash, PgStat_TableStatus *stat, bool nowait); static void pgstat_update_dbentry(PgStat_StatDBEntry *dbentry, @@ -323,6 +292,14 @@ static void pgstat_update_dbentry(PgStat_StatDBEntry *dbentry, * ------------------------------------------------------------ */ + +void +pgstat_initialize(void) +{ + /* Set up a process-exit hook to clean up */ + before_shmem_exit(pgstat_beshutdown_hook, 0); +} + /* * subroutine for pgstat_reset_all */ @@ -2611,66 +2588,6 @@ pgstat_fetch_stat_funcentry(Oid func_id) return funcentry; } - -/* ---------- - * pgstat_fetch_stat_beentry() - - * - * Support function for the SQL-callable pgstat* functions. Returns - * our local copy of the current-activity entry for one backend. - * - * NB: caller is responsible for a check if the user is permitted to see - * this info (especially the querystring). - * ---------- - */ -PgBackendStatus * -pgstat_fetch_stat_beentry(int beid) -{ - pgstat_read_current_status(); - - if (beid < 1 || beid > localNumBackends) - return NULL; - - return &localBackendStatusTable[beid - 1].backendStatus; -} - - -/* ---------- - * pgstat_fetch_stat_local_beentry() - - * - * Like pgstat_fetch_stat_beentry() but with locally computed additions (like - * xid and xmin values of the backend) - * - * NB: caller is responsible for a check if the user is permitted to see - * this info (especially the querystring). - * ---------- - */ -LocalPgBackendStatus * -pgstat_fetch_stat_local_beentry(int beid) -{ - pgstat_read_current_status(); - - if (beid < 1 || beid > localNumBackends) - return NULL; - - return &localBackendStatusTable[beid - 1]; -} - - -/* ---------- - * pgstat_fetch_stat_numbackends() - - * - * Support function for the SQL-callable pgstat* functions. Returns - * the maximum current backend id. - * ---------- - */ -int -pgstat_fetch_stat_numbackends(void) -{ - pgstat_read_current_status(); - - return localNumBackends; -} - /* * --------- * pgstat_fetch_stat_archiver() - @@ -2708,364 +2625,6 @@ pgstat_fetch_global(void) return snapshot_globalStats; } - -/* ------------------------------------------------------------ - * Functions for management of the shared-memory PgBackendStatus array - * ------------------------------------------------------------ - */ - -static PgBackendStatus *BackendStatusArray = NULL; -static PgBackendStatus *MyBEEntry = NULL; -static char *BackendAppnameBuffer = NULL; -static char *BackendClientHostnameBuffer = NULL; -static char *BackendActivityBuffer = NULL; -static Size BackendActivityBufferSize = 0; -#ifdef USE_SSL -static PgBackendSSLStatus *BackendSslStatusBuffer = NULL; -#endif - - -/* - * Report shared-memory space needed by CreateSharedBackendStatus. - */ -Size -BackendStatusShmemSize(void) -{ - Size size; - - /* BackendStatusArray: */ - size = mul_size(sizeof(PgBackendStatus), NumBackendStatSlots); - /* BackendAppnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); - /* BackendClientHostnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); - /* BackendActivityBuffer: */ - size = add_size(size, - mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); -#ifdef USE_SSL - /* BackendSslStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); -#endif - return size; -} - -/* - * Initialize the shared status array and several string buffers - * during postmaster startup. - */ -void -CreateSharedBackendStatus(void) -{ - Size size; - bool found; - int i; - char *buffer; - - /* Create or attach to the shared array */ - size = mul_size(sizeof(PgBackendStatus), NumBackendStatSlots); - BackendStatusArray = (PgBackendStatus *) - ShmemInitStruct("Backend Status Array", size, &found); - - if (!found) - { - /* - * We're the first - initialize. - */ - MemSet(BackendStatusArray, 0, size); - } - - /* Create or attach to the shared appname buffer */ - size = mul_size(NAMEDATALEN, NumBackendStatSlots); - BackendAppnameBuffer = (char *) - ShmemInitStruct("Backend Application Name Buffer", size, &found); - - if (!found) - { - MemSet(BackendAppnameBuffer, 0, size); - - /* Initialize st_appname pointers. */ - buffer = BackendAppnameBuffer; - for (i = 0; i < NumBackendStatSlots; i++) - { - BackendStatusArray[i].st_appname = buffer; - buffer += NAMEDATALEN; - } - } - - /* Create or attach to the shared client hostname buffer */ - size = mul_size(NAMEDATALEN, NumBackendStatSlots); - BackendClientHostnameBuffer = (char *) - ShmemInitStruct("Backend Client Host Name Buffer", size, &found); - - if (!found) - { - MemSet(BackendClientHostnameBuffer, 0, size); - - /* Initialize st_clienthostname pointers. */ - buffer = BackendClientHostnameBuffer; - for (i = 0; i < NumBackendStatSlots; i++) - { - BackendStatusArray[i].st_clienthostname = buffer; - buffer += NAMEDATALEN; - } - } - - /* Create or attach to the shared activity buffer */ - BackendActivityBufferSize = mul_size(pgstat_track_activity_query_size, - NumBackendStatSlots); - BackendActivityBuffer = (char *) - ShmemInitStruct("Backend Activity Buffer", - BackendActivityBufferSize, - &found); - - if (!found) - { - MemSet(BackendActivityBuffer, 0, BackendActivityBufferSize); - - /* Initialize st_activity pointers. */ - buffer = BackendActivityBuffer; - for (i = 0; i < NumBackendStatSlots; i++) - { - BackendStatusArray[i].st_activity_raw = buffer; - buffer += pgstat_track_activity_query_size; - } - } - -#ifdef USE_SSL - /* Create or attach to the shared SSL status buffer */ - size = mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots); - BackendSslStatusBuffer = (PgBackendSSLStatus *) - ShmemInitStruct("Backend SSL Status Buffer", size, &found); - - if (!found) - { - PgBackendSSLStatus *ptr; - - MemSet(BackendSslStatusBuffer, 0, size); - - /* Initialize st_sslstatus pointers. */ - ptr = BackendSslStatusBuffer; - for (i = 0; i < NumBackendStatSlots; i++) - { - BackendStatusArray[i].st_sslstatus = ptr; - ptr++; - } - } -#endif -} - - -/* ---------- - * pgstat_initialize() - - * - * Initialize pgstats state, and set up our on-proc-exit hook. - * Called from InitPostgres and AuxiliaryProcessMain. For auxiliary process, - * MyBackendId is invalid. Otherwise, MyBackendId must be set, - * but we must not have started any transaction yet (since the - * exit hook must run after the last transaction exit). - * NOTE: MyDatabaseId isn't set yet; so the shutdown hook has to be careful. - * ---------- - */ -void -pgstat_initialize(void) -{ - /* Initialize MyBEEntry */ - if (MyBackendId != InvalidBackendId) - { - Assert(MyBackendId >= 1 && MyBackendId <= MaxBackends); - MyBEEntry = &BackendStatusArray[MyBackendId - 1]; - } - else - { - /* Must be an auxiliary process */ - Assert(MyAuxProcType != NotAnAuxProcess); - - /* - * Assign the MyBEEntry for an auxiliary process. Since it doesn't - * have a BackendId, the slot is statically allocated based on the - * auxiliary process type (MyAuxProcType). Backends use slots indexed - * in the range from 1 to MaxBackends (inclusive), so we use - * MaxBackends + AuxBackendType + 1 as the index of the slot for an - * auxiliary process. - */ - MyBEEntry = &BackendStatusArray[MaxBackends + MyAuxProcType]; - } - - /* Set up a process-exit hook to clean up */ - before_shmem_exit(pgstat_beshutdown_hook, 0); -} - -/* ---------- - * pgstat_bestart() - - * - * Initialize this backend's entry in the PgBackendStatus array. - * Called from InitPostgres. - * - * Apart from auxiliary processes, MyBackendId, MyDatabaseId, - * session userid, and application_name must be set for a - * backend (hence, this cannot be combined with pgstat_initialize). - * ---------- - */ -void -pgstat_bestart(void) -{ - SockAddr clientaddr; - volatile PgBackendStatus *beentry; - - /* - * To minimize the time spent modifying the PgBackendStatus entry, fetch - * all the needed data first. - */ - - /* - * We may not have a MyProcPort (eg, if this is the autovacuum process). - * If so, use all-zeroes client address, which is dealt with specially in - * pg_stat_get_backend_client_addr and pg_stat_get_backend_client_port. - */ - if (MyProcPort) - memcpy(&clientaddr, &MyProcPort->raddr, sizeof(clientaddr)); - else - MemSet(&clientaddr, 0, sizeof(clientaddr)); - - /* - * Initialize my status entry, following the protocol of bumping - * st_changecount before and after; and make sure it's even afterwards. We - * use a volatile pointer here to ensure the compiler doesn't try to get - * cute. - */ - beentry = MyBEEntry; - - /* pgstats state must be initialized from pgstat_initialize() */ - Assert(beentry != NULL); - - if (MyBackendId != InvalidBackendId) - { - if (IsAutoVacuumLauncherProcess()) - { - /* Autovacuum Launcher */ - beentry->st_backendType = B_AUTOVAC_LAUNCHER; - } - else if (IsAutoVacuumWorkerProcess()) - { - /* Autovacuum Worker */ - beentry->st_backendType = B_AUTOVAC_WORKER; - } - else if (am_walsender) - { - /* Wal sender */ - beentry->st_backendType = B_WAL_SENDER; - } - else if (IsBackgroundWorker) - { - /* bgworker */ - beentry->st_backendType = B_BG_WORKER; - } - else - { - /* client-backend */ - beentry->st_backendType = B_BACKEND; - } - } - else - { - /* Must be an auxiliary process */ - Assert(MyAuxProcType != NotAnAuxProcess); - switch (MyAuxProcType) - { - case StartupProcess: - beentry->st_backendType = B_STARTUP; - break; - case BgWriterProcess: - beentry->st_backendType = B_BG_WRITER; - break; - case ArchiverProcess: - beentry->st_backendType = B_ARCHIVER; - break; - case CheckpointerProcess: - beentry->st_backendType = B_CHECKPOINTER; - break; - case WalWriterProcess: - beentry->st_backendType = B_WAL_WRITER; - break; - case WalReceiverProcess: - beentry->st_backendType = B_WAL_RECEIVER; - break; - default: - elog(FATAL, "unrecognized process type: %d", - (int) MyAuxProcType); - proc_exit(1); - } - } - - do - { - pgstat_increment_changecount_before(beentry); - } while ((beentry->st_changecount & 1) == 0); - - beentry->st_procpid = MyProcPid; - beentry->st_proc_start_timestamp = MyStartTimestamp; - beentry->st_activity_start_timestamp = 0; - beentry->st_state_start_timestamp = 0; - beentry->st_xact_start_timestamp = 0; - beentry->st_databaseid = MyDatabaseId; - - /* We have userid for client-backends, wal-sender and bgworker processes */ - if (beentry->st_backendType == B_BACKEND - || beentry->st_backendType == B_WAL_SENDER - || beentry->st_backendType == B_BG_WORKER) - beentry->st_userid = GetSessionUserId(); - else - beentry->st_userid = InvalidOid; - - beentry->st_clientaddr = clientaddr; - if (MyProcPort && MyProcPort->remote_hostname) - strlcpy(beentry->st_clienthostname, MyProcPort->remote_hostname, - NAMEDATALEN); - else - beentry->st_clienthostname[0] = '\0'; -#ifdef USE_SSL - if (MyProcPort && MyProcPort->ssl != NULL) - { - beentry->st_ssl = true; - beentry->st_sslstatus->ssl_bits = be_tls_get_cipher_bits(MyProcPort); - beentry->st_sslstatus->ssl_compression = be_tls_get_compression(MyProcPort); - strlcpy(beentry->st_sslstatus->ssl_version, be_tls_get_version(MyProcPort), NAMEDATALEN); - strlcpy(beentry->st_sslstatus->ssl_cipher, be_tls_get_cipher(MyProcPort), NAMEDATALEN); - be_tls_get_peerdn_name(MyProcPort, beentry->st_sslstatus->ssl_clientdn, NAMEDATALEN); - } - else - { - beentry->st_ssl = false; - } -#else - beentry->st_ssl = false; -#endif - beentry->st_state = STATE_UNDEFINED; - beentry->st_appname[0] = '\0'; - beentry->st_activity_raw[0] = '\0'; - /* Also make sure the last byte in each string area is always 0 */ - beentry->st_clienthostname[NAMEDATALEN - 1] = '\0'; - beentry->st_appname[NAMEDATALEN - 1] = '\0'; - beentry->st_activity_raw[pgstat_track_activity_query_size - 1] = '\0'; - beentry->st_progress_command = PROGRESS_COMMAND_INVALID; - beentry->st_progress_command_target = InvalidOid; - - /* - * we don't zero st_progress_param here to save cycles; nobody should - * examine it until st_progress_command has been set to something other - * than PROGRESS_COMMAND_INVALID - */ - - pgstat_increment_changecount_after(beentry); - - /* Update app name to current GUC setting */ - if (application_name) - pgstat_report_appname(application_name); -} - /* * Shut down a single backend's statistics reporting at process exit. * @@ -3078,8 +2637,6 @@ pgstat_bestart(void) static void pgstat_beshutdown_hook(int code, Datum arg) { - volatile PgBackendStatus *beentry = MyBEEntry; - /* * If we got as far as discovering our own database ID, we can report what * we did to the collector. Otherwise, we'd be sending an invalid @@ -3088,1188 +2645,9 @@ pgstat_beshutdown_hook(int code, Datum arg) */ if (OidIsValid(MyDatabaseId)) pgstat_update_stat(true); - - /* - * Clear my status entry, following the protocol of bumping st_changecount - * before and after. We use a volatile pointer here to ensure the - * compiler doesn't try to get cute. - */ - pgstat_increment_changecount_before(beentry); - - beentry->st_procpid = 0; /* mark invalid */ - - pgstat_increment_changecount_after(beentry); } -/* ---------- - * pgstat_report_activity() - - * - * Called from tcop/postgres.c to report what the backend is actually doing - * (but note cmd_str can be NULL for certain cases). - * - * All updates of the status entry follow the protocol of bumping - * st_changecount before and after. We use a volatile pointer here to - * ensure the compiler doesn't try to get cute. - * ---------- - */ -void -pgstat_report_activity(BackendState state, const char *cmd_str) -{ - volatile PgBackendStatus *beentry = MyBEEntry; - TimestampTz start_timestamp; - TimestampTz current_timestamp; - int len = 0; - - TRACE_POSTGRESQL_STATEMENT_STATUS(cmd_str); - - if (!beentry) - return; - - if (!pgstat_track_activities) - { - if (beentry->st_state != STATE_DISABLED) - { - volatile PGPROC *proc = MyProc; - - /* - * track_activities is disabled, but we last reported a - * non-disabled state. As our final update, change the state and - * clear fields we will not be updating anymore. - */ - pgstat_increment_changecount_before(beentry); - beentry->st_state = STATE_DISABLED; - beentry->st_state_start_timestamp = 0; - beentry->st_activity_raw[0] = '\0'; - beentry->st_activity_start_timestamp = 0; - /* st_xact_start_timestamp and wait_event_info are also disabled */ - beentry->st_xact_start_timestamp = 0; - proc->wait_event_info = 0; - pgstat_increment_changecount_after(beentry); - } - return; - } - - /* - * To minimize the time spent modifying the entry, fetch all the needed - * data first. - */ - start_timestamp = GetCurrentStatementStartTimestamp(); - if (cmd_str != NULL) - { - /* - * Compute length of to-be-stored string unaware of multi-byte - * characters. For speed reasons that'll get corrected on read, rather - * than computed every write. - */ - len = Min(strlen(cmd_str), pgstat_track_activity_query_size - 1); - } - current_timestamp = GetCurrentTimestamp(); - - /* - * Now update the status entry - */ - pgstat_increment_changecount_before(beentry); - - beentry->st_state = state; - beentry->st_state_start_timestamp = current_timestamp; - - if (cmd_str != NULL) - { - memcpy((char *) beentry->st_activity_raw, cmd_str, len); - beentry->st_activity_raw[len] = '\0'; - beentry->st_activity_start_timestamp = start_timestamp; - } - - pgstat_increment_changecount_after(beentry); -} - -/*----------- - * pgstat_progress_start_command() - - * - * Set st_progress_command (and st_progress_command_target) in own backend - * entry. Also, zero-initialize st_progress_param array. - *----------- - */ -void -pgstat_progress_start_command(ProgressCommandType cmdtype, Oid relid) -{ - volatile PgBackendStatus *beentry = MyBEEntry; - - if (!beentry || !pgstat_track_activities) - return; - - pgstat_increment_changecount_before(beentry); - beentry->st_progress_command = cmdtype; - beentry->st_progress_command_target = relid; - MemSet(&beentry->st_progress_param, 0, sizeof(beentry->st_progress_param)); - pgstat_increment_changecount_after(beentry); -} - -/*----------- - * pgstat_progress_update_param() - - * - * Update index'th member in st_progress_param[] of own backend entry. - *----------- - */ -void -pgstat_progress_update_param(int index, int64 val) -{ - volatile PgBackendStatus *beentry = MyBEEntry; - - Assert(index >= 0 && index < PGSTAT_NUM_PROGRESS_PARAM); - - if (!beentry || !pgstat_track_activities) - return; - - pgstat_increment_changecount_before(beentry); - beentry->st_progress_param[index] = val; - pgstat_increment_changecount_after(beentry); -} - -/*----------- - * pgstat_progress_update_multi_param() - - * - * Update multiple members in st_progress_param[] of own backend entry. - * This is atomic; readers won't see intermediate states. - *----------- - */ -void -pgstat_progress_update_multi_param(int nparam, const int *index, - const int64 *val) -{ - volatile PgBackendStatus *beentry = MyBEEntry; - int i; - - if (!beentry || !pgstat_track_activities || nparam == 0) - return; - - pgstat_increment_changecount_before(beentry); - - for (i = 0; i < nparam; ++i) - { - Assert(index[i] >= 0 && index[i] < PGSTAT_NUM_PROGRESS_PARAM); - - beentry->st_progress_param[index[i]] = val[i]; - } - - pgstat_increment_changecount_after(beentry); -} - -/*----------- - * pgstat_progress_end_command() - - * - * Reset st_progress_command (and st_progress_command_target) in own backend - * entry. This signals the end of the command. - *----------- - */ -void -pgstat_progress_end_command(void) -{ - volatile PgBackendStatus *beentry = MyBEEntry; - - if (!beentry) - return; - if (!pgstat_track_activities - && beentry->st_progress_command == PROGRESS_COMMAND_INVALID) - return; - - pgstat_increment_changecount_before(beentry); - beentry->st_progress_command = PROGRESS_COMMAND_INVALID; - beentry->st_progress_command_target = InvalidOid; - pgstat_increment_changecount_after(beentry); -} - -/* ---------- - * pgstat_report_appname() - - * - * Called to update our application name. - * ---------- - */ -void -pgstat_report_appname(const char *appname) -{ - volatile PgBackendStatus *beentry = MyBEEntry; - int len; - - if (!beentry) - return; - - /* This should be unnecessary if GUC did its job, but be safe */ - len = pg_mbcliplen(appname, strlen(appname), NAMEDATALEN - 1); - - /* - * Update my status entry, following the protocol of bumping - * st_changecount before and after. We use a volatile pointer here to - * ensure the compiler doesn't try to get cute. - */ - pgstat_increment_changecount_before(beentry); - - memcpy((char *) beentry->st_appname, appname, len); - beentry->st_appname[len] = '\0'; - - pgstat_increment_changecount_after(beentry); -} - -/* - * Report current transaction start timestamp as the specified value. - * Zero means there is no active transaction. - */ -void -pgstat_report_xact_timestamp(TimestampTz tstamp) -{ - volatile PgBackendStatus *beentry = MyBEEntry; - - if (!pgstat_track_activities || !beentry) - return; - - /* - * Update my status entry, following the protocol of bumping - * st_changecount before and after. We use a volatile pointer here to - * ensure the compiler doesn't try to get cute. - */ - pgstat_increment_changecount_before(beentry); - beentry->st_xact_start_timestamp = tstamp; - pgstat_increment_changecount_after(beentry); -} - -/* ---------- - * pgstat_read_current_status() - - * - * Copy the current contents of the PgBackendStatus array to local memory, - * if not already done in this transaction. - * ---------- - */ -static void -pgstat_read_current_status(void) -{ - volatile PgBackendStatus *beentry; - LocalPgBackendStatus *localtable; - LocalPgBackendStatus *localentry; - char *localappname, - *localclienthostname, - *localactivity; -#ifdef USE_SSL - PgBackendSSLStatus *localsslstatus; -#endif - int i; - - Assert(IsUnderPostmaster); - - if (localBackendStatusTable) - return; /* already done */ - - pgstat_setup_memcxt(); - - localtable = (LocalPgBackendStatus *) - MemoryContextAlloc(pgStatLocalContext, - sizeof(LocalPgBackendStatus) * NumBackendStatSlots); - localappname = (char *) - MemoryContextAlloc(pgStatLocalContext, - NAMEDATALEN * NumBackendStatSlots); - localclienthostname = (char *) - MemoryContextAlloc(pgStatLocalContext, - NAMEDATALEN * NumBackendStatSlots); - localactivity = (char *) - MemoryContextAlloc(pgStatLocalContext, - pgstat_track_activity_query_size * NumBackendStatSlots); -#ifdef USE_SSL - localsslstatus = (PgBackendSSLStatus *) - MemoryContextAlloc(pgStatLocalContext, - sizeof(PgBackendSSLStatus) * NumBackendStatSlots); -#endif - - localNumBackends = 0; - - beentry = BackendStatusArray; - localentry = localtable; - for (i = 1; i <= NumBackendStatSlots; i++) - { - /* - * Follow the protocol of retrying if st_changecount changes while we - * copy the entry, or if it's odd. (The check for odd is needed to - * cover the case where we are able to completely copy the entry while - * the source backend is between increment steps.) We use a volatile - * pointer here to ensure the compiler doesn't try to get cute. - */ - for (;;) - { - int before_changecount; - int after_changecount; - - pgstat_save_changecount_before(beentry, before_changecount); - - localentry->backendStatus.st_procpid = beentry->st_procpid; - if (localentry->backendStatus.st_procpid > 0) - { - memcpy(&localentry->backendStatus, (char *) beentry, sizeof(PgBackendStatus)); - - /* - * strcpy is safe even if the string is modified concurrently, - * because there's always a \0 at the end of the buffer. - */ - strcpy(localappname, (char *) beentry->st_appname); - localentry->backendStatus.st_appname = localappname; - strcpy(localclienthostname, (char *) beentry->st_clienthostname); - localentry->backendStatus.st_clienthostname = localclienthostname; - strcpy(localactivity, (char *) beentry->st_activity_raw); - localentry->backendStatus.st_activity_raw = localactivity; - localentry->backendStatus.st_ssl = beentry->st_ssl; -#ifdef USE_SSL - if (beentry->st_ssl) - { - memcpy(localsslstatus, beentry->st_sslstatus, sizeof(PgBackendSSLStatus)); - localentry->backendStatus.st_sslstatus = localsslstatus; - } -#endif - } - - pgstat_save_changecount_after(beentry, after_changecount); - if (before_changecount == after_changecount && - (before_changecount & 1) == 0) - break; - - /* Make sure we can break out of loop if stuck... */ - CHECK_FOR_INTERRUPTS(); - } - - beentry++; - /* Only valid entries get included into the local array */ - if (localentry->backendStatus.st_procpid > 0) - { - BackendIdGetTransactionIds(i, - &localentry->backend_xid, - &localentry->backend_xmin); - - localentry++; - localappname += NAMEDATALEN; - localclienthostname += NAMEDATALEN; - localactivity += pgstat_track_activity_query_size; -#ifdef USE_SSL - localsslstatus++; -#endif - localNumBackends++; - } - } - - /* Set the pointer only after completion of a valid table */ - localBackendStatusTable = localtable; -} - -/* ---------- - * pgstat_get_wait_event_type() - - * - * Return a string representing the current wait event type, backend is - * waiting on. - */ -const char * -pgstat_get_wait_event_type(uint32 wait_event_info) -{ - uint32 classId; - const char *event_type; - - /* report process as not waiting. */ - if (wait_event_info == 0) - return NULL; - - classId = wait_event_info & 0xFF000000; - - switch (classId) - { - case PG_WAIT_LWLOCK: - event_type = "LWLock"; - break; - case PG_WAIT_LOCK: - event_type = "Lock"; - break; - case PG_WAIT_BUFFER_PIN: - event_type = "BufferPin"; - break; - case PG_WAIT_ACTIVITY: - event_type = "Activity"; - break; - case PG_WAIT_CLIENT: - event_type = "Client"; - break; - case PG_WAIT_EXTENSION: - event_type = "Extension"; - break; - case PG_WAIT_IPC: - event_type = "IPC"; - break; - case PG_WAIT_TIMEOUT: - event_type = "Timeout"; - break; - case PG_WAIT_IO: - event_type = "IO"; - break; - default: - event_type = "???"; - break; - } - - return event_type; -} - -/* ---------- - * pgstat_get_wait_event() - - * - * Return a string representing the current wait event, backend is - * waiting on. - */ -const char * -pgstat_get_wait_event(uint32 wait_event_info) -{ - uint32 classId; - uint16 eventId; - const char *event_name; - - /* report process as not waiting. */ - if (wait_event_info == 0) - return NULL; - - classId = wait_event_info & 0xFF000000; - eventId = wait_event_info & 0x0000FFFF; - - switch (classId) - { - case PG_WAIT_LWLOCK: - event_name = GetLWLockIdentifier(classId, eventId); - break; - case PG_WAIT_LOCK: - event_name = GetLockNameFromTagType(eventId); - break; - case PG_WAIT_BUFFER_PIN: - event_name = "BufferPin"; - break; - case PG_WAIT_ACTIVITY: - { - WaitEventActivity w = (WaitEventActivity) wait_event_info; - - event_name = pgstat_get_wait_activity(w); - break; - } - case PG_WAIT_CLIENT: - { - WaitEventClient w = (WaitEventClient) wait_event_info; - - event_name = pgstat_get_wait_client(w); - break; - } - case PG_WAIT_EXTENSION: - event_name = "Extension"; - break; - case PG_WAIT_IPC: - { - WaitEventIPC w = (WaitEventIPC) wait_event_info; - - event_name = pgstat_get_wait_ipc(w); - break; - } - case PG_WAIT_TIMEOUT: - { - WaitEventTimeout w = (WaitEventTimeout) wait_event_info; - - event_name = pgstat_get_wait_timeout(w); - break; - } - case PG_WAIT_IO: - { - WaitEventIO w = (WaitEventIO) wait_event_info; - - event_name = pgstat_get_wait_io(w); - break; - } - default: - event_name = "unknown wait event"; - break; - } - - return event_name; -} - -/* ---------- - * pgstat_get_wait_activity() - - * - * Convert WaitEventActivity to string. - * ---------- - */ -static const char * -pgstat_get_wait_activity(WaitEventActivity w) -{ - const char *event_name = "unknown wait event"; - - switch (w) - { - case WAIT_EVENT_ARCHIVER_MAIN: - event_name = "ArchiverMain"; - break; - case WAIT_EVENT_AUTOVACUUM_MAIN: - event_name = "AutoVacuumMain"; - break; - case WAIT_EVENT_BGWRITER_HIBERNATE: - event_name = "BgWriterHibernate"; - break; - case WAIT_EVENT_BGWRITER_MAIN: - event_name = "BgWriterMain"; - break; - case WAIT_EVENT_CHECKPOINTER_MAIN: - event_name = "CheckpointerMain"; - break; - case WAIT_EVENT_LOGICAL_APPLY_MAIN: - event_name = "LogicalApplyMain"; - break; - case WAIT_EVENT_LOGICAL_LAUNCHER_MAIN: - event_name = "LogicalLauncherMain"; - break; - case WAIT_EVENT_PGSTAT_MAIN: - event_name = "PgStatMain"; - break; - case WAIT_EVENT_RECOVERY_WAL_ALL: - event_name = "RecoveryWalAll"; - break; - case WAIT_EVENT_RECOVERY_WAL_STREAM: - event_name = "RecoveryWalStream"; - break; - case WAIT_EVENT_SYSLOGGER_MAIN: - event_name = "SysLoggerMain"; - break; - case WAIT_EVENT_WAL_RECEIVER_MAIN: - event_name = "WalReceiverMain"; - break; - case WAIT_EVENT_WAL_SENDER_MAIN: - event_name = "WalSenderMain"; - break; - case WAIT_EVENT_WAL_WRITER_MAIN: - event_name = "WalWriterMain"; - break; - /* no default case, so that compiler will warn */ - } - - return event_name; -} - -/* ---------- - * pgstat_get_wait_client() - - * - * Convert WaitEventClient to string. - * ---------- - */ -static const char * -pgstat_get_wait_client(WaitEventClient w) -{ - const char *event_name = "unknown wait event"; - - switch (w) - { - case WAIT_EVENT_CLIENT_READ: - event_name = "ClientRead"; - break; - case WAIT_EVENT_CLIENT_WRITE: - event_name = "ClientWrite"; - break; - case WAIT_EVENT_LIBPQWALRECEIVER_CONNECT: - event_name = "LibPQWalReceiverConnect"; - break; - case WAIT_EVENT_LIBPQWALRECEIVER_RECEIVE: - event_name = "LibPQWalReceiverReceive"; - break; - case WAIT_EVENT_SSL_OPEN_SERVER: - event_name = "SSLOpenServer"; - break; - case WAIT_EVENT_WAL_RECEIVER_WAIT_START: - event_name = "WalReceiverWaitStart"; - break; - case WAIT_EVENT_WAL_SENDER_WAIT_WAL: - event_name = "WalSenderWaitForWAL"; - break; - case WAIT_EVENT_WAL_SENDER_WRITE_DATA: - event_name = "WalSenderWriteData"; - break; - /* no default case, so that compiler will warn */ - } - - return event_name; -} - -/* ---------- - * pgstat_get_wait_ipc() - - * - * Convert WaitEventIPC to string. - * ---------- - */ -static const char * -pgstat_get_wait_ipc(WaitEventIPC w) -{ - const char *event_name = "unknown wait event"; - - switch (w) - { - case WAIT_EVENT_BGWORKER_SHUTDOWN: - event_name = "BgWorkerShutdown"; - break; - case WAIT_EVENT_BGWORKER_STARTUP: - event_name = "BgWorkerStartup"; - break; - case WAIT_EVENT_BTREE_PAGE: - event_name = "BtreePage"; - break; - case WAIT_EVENT_CLOG_GROUP_UPDATE: - event_name = "ClogGroupUpdate"; - break; - case WAIT_EVENT_EXECUTE_GATHER: - event_name = "ExecuteGather"; - break; - case WAIT_EVENT_HASH_BATCH_ALLOCATING: - event_name = "Hash/Batch/Allocating"; - break; - case WAIT_EVENT_HASH_BATCH_ELECTING: - event_name = "Hash/Batch/Electing"; - break; - case WAIT_EVENT_HASH_BATCH_LOADING: - event_name = "Hash/Batch/Loading"; - break; - case WAIT_EVENT_HASH_BUILD_ALLOCATING: - event_name = "Hash/Build/Allocating"; - break; - case WAIT_EVENT_HASH_BUILD_ELECTING: - event_name = "Hash/Build/Electing"; - break; - case WAIT_EVENT_HASH_BUILD_HASHING_INNER: - event_name = "Hash/Build/HashingInner"; - break; - case WAIT_EVENT_HASH_BUILD_HASHING_OUTER: - event_name = "Hash/Build/HashingOuter"; - break; - case WAIT_EVENT_HASH_GROW_BATCHES_ALLOCATING: - event_name = "Hash/GrowBatches/Allocating"; - break; - case WAIT_EVENT_HASH_GROW_BATCHES_DECIDING: - event_name = "Hash/GrowBatches/Deciding"; - break; - case WAIT_EVENT_HASH_GROW_BATCHES_ELECTING: - event_name = "Hash/GrowBatches/Electing"; - break; - case WAIT_EVENT_HASH_GROW_BATCHES_FINISHING: - event_name = "Hash/GrowBatches/Finishing"; - break; - case WAIT_EVENT_HASH_GROW_BATCHES_REPARTITIONING: - event_name = "Hash/GrowBatches/Repartitioning"; - break; - case WAIT_EVENT_HASH_GROW_BUCKETS_ALLOCATING: - event_name = "Hash/GrowBuckets/Allocating"; - break; - case WAIT_EVENT_HASH_GROW_BUCKETS_ELECTING: - event_name = "Hash/GrowBuckets/Electing"; - break; - case WAIT_EVENT_HASH_GROW_BUCKETS_REINSERTING: - event_name = "Hash/GrowBuckets/Reinserting"; - break; - case WAIT_EVENT_LOGICAL_SYNC_DATA: - event_name = "LogicalSyncData"; - break; - case WAIT_EVENT_LOGICAL_SYNC_STATE_CHANGE: - event_name = "LogicalSyncStateChange"; - break; - case WAIT_EVENT_MQ_INTERNAL: - event_name = "MessageQueueInternal"; - break; - case WAIT_EVENT_MQ_PUT_MESSAGE: - event_name = "MessageQueuePutMessage"; - break; - case WAIT_EVENT_MQ_RECEIVE: - event_name = "MessageQueueReceive"; - break; - case WAIT_EVENT_MQ_SEND: - event_name = "MessageQueueSend"; - break; - case WAIT_EVENT_PARALLEL_BITMAP_SCAN: - event_name = "ParallelBitmapScan"; - break; - case WAIT_EVENT_PARALLEL_CREATE_INDEX_SCAN: - event_name = "ParallelCreateIndexScan"; - break; - case WAIT_EVENT_PARALLEL_FINISH: - event_name = "ParallelFinish"; - break; - case WAIT_EVENT_PROCARRAY_GROUP_UPDATE: - event_name = "ProcArrayGroupUpdate"; - break; - case WAIT_EVENT_PROMOTE: - event_name = "Promote"; - break; - case WAIT_EVENT_REPLICATION_ORIGIN_DROP: - event_name = "ReplicationOriginDrop"; - break; - case WAIT_EVENT_REPLICATION_SLOT_DROP: - event_name = "ReplicationSlotDrop"; - break; - case WAIT_EVENT_SAFE_SNAPSHOT: - event_name = "SafeSnapshot"; - break; - case WAIT_EVENT_SYNC_REP: - event_name = "SyncRep"; - break; - /* no default case, so that compiler will warn */ - } - - return event_name; -} - -/* ---------- - * pgstat_get_wait_timeout() - - * - * Convert WaitEventTimeout to string. - * ---------- - */ -static const char * -pgstat_get_wait_timeout(WaitEventTimeout w) -{ - const char *event_name = "unknown wait event"; - - switch (w) - { - case WAIT_EVENT_BASE_BACKUP_THROTTLE: - event_name = "BaseBackupThrottle"; - break; - case WAIT_EVENT_PG_SLEEP: - event_name = "PgSleep"; - break; - case WAIT_EVENT_RECOVERY_APPLY_DELAY: - event_name = "RecoveryApplyDelay"; - break; - /* no default case, so that compiler will warn */ - } - - return event_name; -} - -/* ---------- - * pgstat_get_wait_io() - - * - * Convert WaitEventIO to string. - * ---------- - */ -static const char * -pgstat_get_wait_io(WaitEventIO w) -{ - const char *event_name = "unknown wait event"; - - switch (w) - { - case WAIT_EVENT_BUFFILE_READ: - event_name = "BufFileRead"; - break; - case WAIT_EVENT_BUFFILE_WRITE: - event_name = "BufFileWrite"; - break; - case WAIT_EVENT_CONTROL_FILE_READ: - event_name = "ControlFileRead"; - break; - case WAIT_EVENT_CONTROL_FILE_SYNC: - event_name = "ControlFileSync"; - break; - case WAIT_EVENT_CONTROL_FILE_SYNC_UPDATE: - event_name = "ControlFileSyncUpdate"; - break; - case WAIT_EVENT_CONTROL_FILE_WRITE: - event_name = "ControlFileWrite"; - break; - case WAIT_EVENT_CONTROL_FILE_WRITE_UPDATE: - event_name = "ControlFileWriteUpdate"; - break; - case WAIT_EVENT_COPY_FILE_READ: - event_name = "CopyFileRead"; - break; - case WAIT_EVENT_COPY_FILE_WRITE: - event_name = "CopyFileWrite"; - break; - case WAIT_EVENT_DATA_FILE_EXTEND: - event_name = "DataFileExtend"; - break; - case WAIT_EVENT_DATA_FILE_FLUSH: - event_name = "DataFileFlush"; - break; - case WAIT_EVENT_DATA_FILE_IMMEDIATE_SYNC: - event_name = "DataFileImmediateSync"; - break; - case WAIT_EVENT_DATA_FILE_PREFETCH: - event_name = "DataFilePrefetch"; - break; - case WAIT_EVENT_DATA_FILE_READ: - event_name = "DataFileRead"; - break; - case WAIT_EVENT_DATA_FILE_SYNC: - event_name = "DataFileSync"; - break; - case WAIT_EVENT_DATA_FILE_TRUNCATE: - event_name = "DataFileTruncate"; - break; - case WAIT_EVENT_DATA_FILE_WRITE: - event_name = "DataFileWrite"; - break; - case WAIT_EVENT_DSM_FILL_ZERO_WRITE: - event_name = "DSMFillZeroWrite"; - break; - case WAIT_EVENT_LOCK_FILE_ADDTODATADIR_READ: - event_name = "LockFileAddToDataDirRead"; - break; - case WAIT_EVENT_LOCK_FILE_ADDTODATADIR_SYNC: - event_name = "LockFileAddToDataDirSync"; - break; - case WAIT_EVENT_LOCK_FILE_ADDTODATADIR_WRITE: - event_name = "LockFileAddToDataDirWrite"; - break; - case WAIT_EVENT_LOCK_FILE_CREATE_READ: - event_name = "LockFileCreateRead"; - break; - case WAIT_EVENT_LOCK_FILE_CREATE_SYNC: - event_name = "LockFileCreateSync"; - break; - case WAIT_EVENT_LOCK_FILE_CREATE_WRITE: - event_name = "LockFileCreateWRITE"; - break; - case WAIT_EVENT_LOCK_FILE_RECHECKDATADIR_READ: - event_name = "LockFileReCheckDataDirRead"; - break; - case WAIT_EVENT_LOGICAL_REWRITE_CHECKPOINT_SYNC: - event_name = "LogicalRewriteCheckpointSync"; - break; - case WAIT_EVENT_LOGICAL_REWRITE_MAPPING_SYNC: - event_name = "LogicalRewriteMappingSync"; - break; - case WAIT_EVENT_LOGICAL_REWRITE_MAPPING_WRITE: - event_name = "LogicalRewriteMappingWrite"; - break; - case WAIT_EVENT_LOGICAL_REWRITE_SYNC: - event_name = "LogicalRewriteSync"; - break; - case WAIT_EVENT_LOGICAL_REWRITE_TRUNCATE: - event_name = "LogicalRewriteTruncate"; - break; - case WAIT_EVENT_LOGICAL_REWRITE_WRITE: - event_name = "LogicalRewriteWrite"; - break; - case WAIT_EVENT_RELATION_MAP_READ: - event_name = "RelationMapRead"; - break; - case WAIT_EVENT_RELATION_MAP_SYNC: - event_name = "RelationMapSync"; - break; - case WAIT_EVENT_RELATION_MAP_WRITE: - event_name = "RelationMapWrite"; - break; - case WAIT_EVENT_REORDER_BUFFER_READ: - event_name = "ReorderBufferRead"; - break; - case WAIT_EVENT_REORDER_BUFFER_WRITE: - event_name = "ReorderBufferWrite"; - break; - case WAIT_EVENT_REORDER_LOGICAL_MAPPING_READ: - event_name = "ReorderLogicalMappingRead"; - break; - case WAIT_EVENT_REPLICATION_SLOT_READ: - event_name = "ReplicationSlotRead"; - break; - case WAIT_EVENT_REPLICATION_SLOT_RESTORE_SYNC: - event_name = "ReplicationSlotRestoreSync"; - break; - case WAIT_EVENT_REPLICATION_SLOT_SYNC: - event_name = "ReplicationSlotSync"; - break; - case WAIT_EVENT_REPLICATION_SLOT_WRITE: - event_name = "ReplicationSlotWrite"; - break; - case WAIT_EVENT_SLRU_FLUSH_SYNC: - event_name = "SLRUFlushSync"; - break; - case WAIT_EVENT_SLRU_READ: - event_name = "SLRURead"; - break; - case WAIT_EVENT_SLRU_SYNC: - event_name = "SLRUSync"; - break; - case WAIT_EVENT_SLRU_WRITE: - event_name = "SLRUWrite"; - break; - case WAIT_EVENT_SNAPBUILD_READ: - event_name = "SnapbuildRead"; - break; - case WAIT_EVENT_SNAPBUILD_SYNC: - event_name = "SnapbuildSync"; - break; - case WAIT_EVENT_SNAPBUILD_WRITE: - event_name = "SnapbuildWrite"; - break; - case WAIT_EVENT_TIMELINE_HISTORY_FILE_SYNC: - event_name = "TimelineHistoryFileSync"; - break; - case WAIT_EVENT_TIMELINE_HISTORY_FILE_WRITE: - event_name = "TimelineHistoryFileWrite"; - break; - case WAIT_EVENT_TIMELINE_HISTORY_READ: - event_name = "TimelineHistoryRead"; - break; - case WAIT_EVENT_TIMELINE_HISTORY_SYNC: - event_name = "TimelineHistorySync"; - break; - case WAIT_EVENT_TIMELINE_HISTORY_WRITE: - event_name = "TimelineHistoryWrite"; - break; - case WAIT_EVENT_TWOPHASE_FILE_READ: - event_name = "TwophaseFileRead"; - break; - case WAIT_EVENT_TWOPHASE_FILE_SYNC: - event_name = "TwophaseFileSync"; - break; - case WAIT_EVENT_TWOPHASE_FILE_WRITE: - event_name = "TwophaseFileWrite"; - break; - case WAIT_EVENT_WALSENDER_TIMELINE_HISTORY_READ: - event_name = "WALSenderTimelineHistoryRead"; - break; - case WAIT_EVENT_WAL_BOOTSTRAP_SYNC: - event_name = "WALBootstrapSync"; - break; - case WAIT_EVENT_WAL_BOOTSTRAP_WRITE: - event_name = "WALBootstrapWrite"; - break; - case WAIT_EVENT_WAL_COPY_READ: - event_name = "WALCopyRead"; - break; - case WAIT_EVENT_WAL_COPY_SYNC: - event_name = "WALCopySync"; - break; - case WAIT_EVENT_WAL_COPY_WRITE: - event_name = "WALCopyWrite"; - break; - case WAIT_EVENT_WAL_INIT_SYNC: - event_name = "WALInitSync"; - break; - case WAIT_EVENT_WAL_INIT_WRITE: - event_name = "WALInitWrite"; - break; - case WAIT_EVENT_WAL_READ: - event_name = "WALRead"; - break; - case WAIT_EVENT_WAL_SYNC: - event_name = "WALSync"; - break; - case WAIT_EVENT_WAL_SYNC_METHOD_ASSIGN: - event_name = "WALSyncMethodAssign"; - break; - case WAIT_EVENT_WAL_WRITE: - event_name = "WALWrite"; - break; - - /* no default case, so that compiler will warn */ - } - - return event_name; -} - - -/* ---------- - * pgstat_get_backend_current_activity() - - * - * Return a string representing the current activity of the backend with - * the specified PID. This looks directly at the BackendStatusArray, - * and so will provide current information regardless of the age of our - * transaction's snapshot of the status array. - * - * It is the caller's responsibility to invoke this only for backends whose - * state is expected to remain stable while the result is in use. The - * only current use is in deadlock reporting, where we can expect that - * the target backend is blocked on a lock. (There are corner cases - * where the target's wait could get aborted while we are looking at it, - * but the very worst consequence is to return a pointer to a string - * that's been changed, so we won't worry too much.) - * - * Note: return strings for special cases match pg_stat_get_backend_activity. - * ---------- - */ -const char * -pgstat_get_backend_current_activity(int pid, bool checkUser) -{ - PgBackendStatus *beentry; - int i; - - beentry = BackendStatusArray; - for (i = 1; i <= MaxBackends; i++) - { - /* - * Although we expect the target backend's entry to be stable, that - * doesn't imply that anyone else's is. To avoid identifying the - * wrong backend, while we check for a match to the desired PID we - * must follow the protocol of retrying if st_changecount changes - * while we examine the entry, or if it's odd. (This might be - * unnecessary, since fetching or storing an int is almost certainly - * atomic, but let's play it safe.) We use a volatile pointer here to - * ensure the compiler doesn't try to get cute. - */ - volatile PgBackendStatus *vbeentry = beentry; - bool found; - - for (;;) - { - int before_changecount; - int after_changecount; - - pgstat_save_changecount_before(vbeentry, before_changecount); - - found = (vbeentry->st_procpid == pid); - - pgstat_save_changecount_after(vbeentry, after_changecount); - - if (before_changecount == after_changecount && - (before_changecount & 1) == 0) - break; - - /* Make sure we can break out of loop if stuck... */ - CHECK_FOR_INTERRUPTS(); - } - - if (found) - { - /* Now it is safe to use the non-volatile pointer */ - if (checkUser && !superuser() && beentry->st_userid != GetUserId()) - return ""; - else if (*(beentry->st_activity_raw) == '\0') - return ""; - else - { - /* this'll leak a bit of memory, but that seems acceptable */ - return pgstat_clip_activity(beentry->st_activity_raw); - } - } - - beentry++; - } - - /* If we get here, caller is in error ... */ - return ""; -} - -/* ---------- - * pgstat_get_crashed_backend_activity() - - * - * Return a string representing the current activity of the backend with - * the specified PID. Like the function above, but reads shared memory with - * the expectation that it may be corrupt. On success, copy the string - * into the "buffer" argument and return that pointer. On failure, - * return NULL. - * - * This function is only intended to be used by the postmaster to report the - * query that crashed a backend. In particular, no attempt is made to - * follow the correct concurrency protocol when accessing the - * BackendStatusArray. But that's OK, in the worst case we'll return a - * corrupted message. We also must take care not to trip on ereport(ERROR). - * ---------- - */ -const char * -pgstat_get_crashed_backend_activity(int pid, char *buffer, int buflen) -{ - volatile PgBackendStatus *beentry; - int i; - - beentry = BackendStatusArray; - - /* - * We probably shouldn't get here before shared memory has been set up, - * but be safe. - */ - if (beentry == NULL || BackendActivityBuffer == NULL) - return NULL; - - for (i = 1; i <= MaxBackends; i++) - { - if (beentry->st_procpid == pid) - { - /* Read pointer just once, so it can't change after validation */ - const char *activity = beentry->st_activity_raw; - const char *activity_last; - - /* - * We mustn't access activity string before we verify that it - * falls within the BackendActivityBuffer. To make sure that the - * entire string including its ending is contained within the - * buffer, subtract one activity length from the buffer size. - */ - activity_last = BackendActivityBuffer + BackendActivityBufferSize - - pgstat_track_activity_query_size; - - if (activity < BackendActivityBuffer || - activity > activity_last) - return NULL; - - /* If no string available, no point in a report */ - if (activity[0] == '\0') - return NULL; - - /* - * Copy only ASCII-safe characters so we don't run into encoding - * problems when reporting the message; and be sure not to run off - * the end of memory. As only ASCII characters are reported, it - * doesn't seem necessary to perform multibyte aware clipping. - */ - ascii_safe_strlcpy(buffer, activity, - Min(buflen, pgstat_track_activity_query_size)); - - return buffer; - } - - beentry++; - } - - /* PID not found */ - return NULL; -} - -const char * -pgstat_get_backend_desc(BackendType backendType) -{ - const char *backendDesc = "unknown process type"; - - switch (backendType) - { - case B_AUTOVAC_LAUNCHER: - backendDesc = "autovacuum launcher"; - break; - case B_AUTOVAC_WORKER: - backendDesc = "autovacuum worker"; - break; - case B_BACKEND: - backendDesc = "client backend"; - break; - case B_BG_WORKER: - backendDesc = "background worker"; - break; - case B_BG_WRITER: - backendDesc = "background writer"; - break; - case B_ARCHIVER: - backendDesc = "archiver"; - break; - case B_CHECKPOINTER: - backendDesc = "checkpointer"; - break; - case B_STARTUP: - backendDesc = "startup"; - break; - case B_WAL_RECEIVER: - backendDesc = "walreceiver"; - break; - case B_WAL_SENDER: - backendDesc = "walsender"; - break; - case B_WAL_WRITER: - backendDesc = "walwriter"; - break; - } - - return backendDesc; -} - /* ------------------------------------------------------------ * Local support functions follow * ------------------------------------------------------------ @@ -5412,22 +3790,6 @@ backend_get_func_etnry(PgStat_StatDBEntry *dbent, Oid funcid, bool oneshot) funcid); } -/* ---------- - * pgstat_setup_memcxt() - - * - * Create pgStatLocalContext, if not already done. - * ---------- - */ -static void -pgstat_setup_memcxt(void) -{ - if (!pgStatLocalContext) - pgStatLocalContext = AllocSetContextCreate(TopMemoryContext, - "Statistics snapshot", - ALLOCSET_SMALL_SIZES); -} - - /* ---------- * pgstat_clear_snapshot() - * @@ -5443,6 +3805,8 @@ pgstat_clear_snapshot(void) { int param = 0; /* only the address is significant */ + bestatus_clear_snapshot(); + /* Release memory, if any was allocated */ if (pgStatLocalContext) MemoryContextDelete(pgStatLocalContext); @@ -5450,8 +3814,6 @@ pgstat_clear_snapshot(void) /* Reset variables */ pgStatLocalContext = NULL; pgStatDBHash = NULL; - localBackendStatusTable = NULL; - localNumBackends = 0; /* * the parameter inform the function that it is not called from @@ -5557,47 +3919,18 @@ pgstat_update_dbentry(PgStat_StatDBEntry *dbentry, PgStat_TableStatus *stat) dbentry->n_blocks_hit += stat->t_counts.t_blocks_hit; } - -/* - * Convert a potentially unsafely truncated activity string (see - * PgBackendStatus.st_activity_raw's documentation) into a correctly truncated - * one. +/* ---------- + * pgstat_setup_memcxt() - * - * The returned string is allocated in the caller's memory context and may be - * freed. + * Create pgStatLocalContext, if not already done. + * ---------- */ -char * -pgstat_clip_activity(const char *raw_activity) +static void +pgstat_setup_memcxt(void) { - char *activity; - int rawlen; - int cliplen; - - /* - * Some callers, like pgstat_get_backend_current_activity(), do not - * guarantee that the buffer isn't concurrently modified. We try to take - * care that the buffer is always terminated by a NUL byte regardless, but - * let's still be paranoid about the string's length. In those cases the - * underlying buffer is guaranteed to be pgstat_track_activity_query_size - * large. - */ - activity = pnstrdup(raw_activity, pgstat_track_activity_query_size - 1); - - /* now double-guaranteed to be NUL terminated */ - rawlen = strlen(activity); - - /* - * All supported server-encodings make it possible to determine the length - * of a multi-byte character from its first byte (this is not the case for - * client encodings, see GB18030). As st_activity is always stored using - * server encoding, this allows us to perform multi-byte aware truncation, - * even if the string earlier was truncated in the middle of a multi-byte - * character. - */ - cliplen = pg_mbcliplen(activity, rawlen, - pgstat_track_activity_query_size - 1); - - activity[cliplen] = '\0'; - - return activity; + if (!pgStatLocalContext) + pgStatLocalContext = AllocSetContextCreate(TopMemoryContext, + "Statistics snapshot", + ALLOCSET_SMALL_SIZES); } + diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c index e794a81c4c..d92c7c935d 100644 --- a/src/backend/storage/buffer/bufmgr.c +++ b/src/backend/storage/buffer/bufmgr.c @@ -34,6 +34,7 @@ #include #include "access/xlog.h" +#include "bestatus.h" #include "catalog/catalog.h" #include "catalog/storage.h" #include "executor/instrument.h" diff --git a/src/backend/storage/file/buffile.c b/src/backend/storage/file/buffile.c index e93813d973..24c15be240 100644 --- a/src/backend/storage/file/buffile.c +++ b/src/backend/storage/file/buffile.c @@ -41,9 +41,9 @@ #include "postgres.h" +#include "bestatus.h" #include "executor/instrument.h" #include "miscadmin.h" -#include "pgstat.h" #include "storage/fd.h" #include "storage/buffile.h" #include "storage/buf_internals.h" diff --git a/src/backend/storage/file/copydir.c b/src/backend/storage/file/copydir.c index 4a0d23b11e..bee2923068 100644 --- a/src/backend/storage/file/copydir.c +++ b/src/backend/storage/file/copydir.c @@ -22,10 +22,10 @@ #include #include +#include "bestatus.h" #include "storage/copydir.h" #include "storage/fd.h" #include "miscadmin.h" -#include "pgstat.h" /* * copydir: copy a directory @@ -186,9 +186,9 @@ copy_file(char *fromfile, char *tofile) flush_offset = offset; } - pgstat_report_wait_start(WAIT_EVENT_COPY_FILE_READ); + bestatus_report_wait_start(WAIT_EVENT_COPY_FILE_READ); nbytes = read(srcfd, buffer, COPY_BUF_SIZE); - pgstat_report_wait_end(); + bestatus_report_wait_end(); if (nbytes < 0) ereport(ERROR, (errcode_for_file_access(), @@ -196,10 +196,10 @@ copy_file(char *fromfile, char *tofile) if (nbytes == 0) break; errno = 0; - pgstat_report_wait_start(WAIT_EVENT_COPY_FILE_WRITE); + bestatus_report_wait_start(WAIT_EVENT_COPY_FILE_WRITE); if ((int) write(dstfd, buffer, nbytes) != nbytes) { - pgstat_report_wait_end(); + bestatus_report_wait_end(); /* if write didn't set errno, assume problem is no disk space */ if (errno == 0) errno = ENOSPC; @@ -207,7 +207,7 @@ copy_file(char *fromfile, char *tofile) (errcode_for_file_access(), errmsg("could not write to file \"%s\": %m", tofile))); } - pgstat_report_wait_end(); + bestatus_report_wait_end(); } if (offset > flush_offset) diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c index 8dd51f1767..c0e973c953 100644 --- a/src/backend/storage/file/fd.c +++ b/src/backend/storage/file/fd.c @@ -82,6 +82,7 @@ #include "miscadmin.h" #include "access/xact.h" #include "access/xlog.h" +#include "bestatus.h" #include "catalog/pg_tablespace.h" #include "common/file_perm.h" #include "pgstat.h" @@ -1844,10 +1845,10 @@ FilePrefetch(File file, off_t offset, int amount, uint32 wait_event_info) if (returnCode < 0) return returnCode; - pgstat_report_wait_start(wait_event_info); + bestatus_report_wait_start(wait_event_info); returnCode = posix_fadvise(VfdCache[file].fd, offset, amount, POSIX_FADV_WILLNEED); - pgstat_report_wait_end(); + bestatus_report_wait_end(); return returnCode; #else @@ -1878,9 +1879,9 @@ FileWriteback(File file, off_t offset, off_t nbytes, uint32 wait_event_info) if (returnCode < 0) return; - pgstat_report_wait_start(wait_event_info); + bestatus_report_wait_start(wait_event_info); pg_flush_data(VfdCache[file].fd, offset, nbytes); - pgstat_report_wait_end(); + bestatus_report_wait_end(); } int @@ -1903,9 +1904,9 @@ FileRead(File file, char *buffer, int amount, uint32 wait_event_info) vfdP = &VfdCache[file]; retry: - pgstat_report_wait_start(wait_event_info); + bestatus_report_wait_start(wait_event_info); returnCode = read(vfdP->fd, buffer, amount); - pgstat_report_wait_end(); + bestatus_report_wait_end(); if (returnCode >= 0) { @@ -2006,9 +2007,9 @@ FileWrite(File file, char *buffer, int amount, uint32 wait_event_info) retry: errno = 0; - pgstat_report_wait_start(wait_event_info); + bestatus_report_wait_start(wait_event_info); returnCode = write(vfdP->fd, buffer, amount); - pgstat_report_wait_end(); + bestatus_report_wait_end(); /* if write didn't set errno, assume problem is no disk space */ if (returnCode != amount && errno == 0) @@ -2082,9 +2083,9 @@ FileSync(File file, uint32 wait_event_info) if (returnCode < 0) return returnCode; - pgstat_report_wait_start(wait_event_info); + bestatus_report_wait_start(wait_event_info); returnCode = pg_fsync(VfdCache[file].fd); - pgstat_report_wait_end(); + bestatus_report_wait_end(); return returnCode; } @@ -2191,9 +2192,9 @@ FileTruncate(File file, off_t offset, uint32 wait_event_info) if (returnCode < 0) return returnCode; - pgstat_report_wait_start(wait_event_info); + bestatus_report_wait_start(wait_event_info); returnCode = ftruncate(VfdCache[file].fd, offset); - pgstat_report_wait_end(); + bestatus_report_wait_end(); if (returnCode == 0 && VfdCache[file].fileSize > offset) { diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c index 70f899e765..6616751378 100644 --- a/src/backend/storage/ipc/dsm_impl.c +++ b/src/backend/storage/ipc/dsm_impl.c @@ -61,8 +61,8 @@ #ifdef HAVE_SYS_SHM_H #include #endif +#include "bestatus.h" #include "common/file_perm.h" -#include "pgstat.h" #include "portability/mem.h" #include "storage/dsm_impl.h" @@ -970,12 +970,12 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size, if (goal > ZBUFFER_SIZE) goal = ZBUFFER_SIZE; - pgstat_report_wait_start(WAIT_EVENT_DSM_FILL_ZERO_WRITE); + bestatus_report_wait_start(WAIT_EVENT_DSM_FILL_ZERO_WRITE); if (write(fd, zbuffer, goal) == goal) remaining -= goal; else success = false; - pgstat_report_wait_end(); + bestatus_report_wait_end(); } if (!success) diff --git a/src/backend/storage/ipc/latch.c b/src/backend/storage/ipc/latch.c index f6dda9cc9a..3b646a4cbb 100644 --- a/src/backend/storage/ipc/latch.c +++ b/src/backend/storage/ipc/latch.c @@ -43,8 +43,8 @@ #include #endif +#include "bestatus.h" #include "miscadmin.h" -#include "pgstat.h" #include "port/atomics.h" #include "portability/instr_time.h" #include "postmaster/postmaster.h" @@ -940,7 +940,7 @@ WaitEventSetWait(WaitEventSet *set, long timeout, cur_timeout = timeout; } - pgstat_report_wait_start(wait_event_info); + bestatus_report_wait_start(wait_event_info); #ifndef WIN32 waiting = true; @@ -1019,7 +1019,7 @@ WaitEventSetWait(WaitEventSet *set, long timeout, waiting = false; #endif - pgstat_report_wait_end(); + bestatus_report_wait_end(); return returned_events; } diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index 908f62d37e..8c86239463 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -51,9 +51,9 @@ #include "access/twophase.h" #include "access/xact.h" #include "access/xlog.h" +#include "bestatus.h" #include "catalog/catalog.h" #include "miscadmin.h" -#include "pgstat.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/spin.h" @@ -515,7 +515,7 @@ ProcArrayGroupClearXid(PGPROC *proc, TransactionId latestXid) int extraWaits = 0; /* Sleep until the leader clears our XID. */ - pgstat_report_wait_start(WAIT_EVENT_PROCARRAY_GROUP_UPDATE); + bestatus_report_wait_start(WAIT_EVENT_PROCARRAY_GROUP_UPDATE); for (;;) { /* acts as a read barrier */ @@ -524,7 +524,7 @@ ProcArrayGroupClearXid(PGPROC *proc, TransactionId latestXid) break; extraWaits++; } - pgstat_report_wait_end(); + bestatus_report_wait_end(); Assert(pg_atomic_read_u32(&proc->procArrayGroupNext) == INVALID_PGPROCNO); diff --git a/src/backend/storage/ipc/shm_mq.c b/src/backend/storage/ipc/shm_mq.c index fde71afd47..a0a5582aac 100644 --- a/src/backend/storage/ipc/shm_mq.c +++ b/src/backend/storage/ipc/shm_mq.c @@ -18,8 +18,8 @@ #include "postgres.h" +#include "bestatus.h" #include "miscadmin.h" -#include "pgstat.h" #include "postmaster/bgworker.h" #include "storage/procsignal.h" #include "storage/shm_mq.h" diff --git a/src/backend/storage/ipc/standby.c b/src/backend/storage/ipc/standby.c index c9bb3e987d..0a9181cd9d 100644 --- a/src/backend/storage/ipc/standby.c +++ b/src/backend/storage/ipc/standby.c @@ -21,8 +21,8 @@ #include "access/xact.h" #include "access/xlog.h" #include "access/xloginsert.h" +#include "bestatus.h" #include "miscadmin.h" -#include "pgstat.h" #include "storage/bufmgr.h" #include "storage/lmgr.h" #include "storage/proc.h" diff --git a/src/backend/storage/lmgr/deadlock.c b/src/backend/storage/lmgr/deadlock.c index aeaf1f3ab4..a473dee3a8 100644 --- a/src/backend/storage/lmgr/deadlock.c +++ b/src/backend/storage/lmgr/deadlock.c @@ -25,6 +25,7 @@ */ #include "postgres.h" +#include "bestatus.h" #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" @@ -1127,7 +1128,7 @@ DeadLockReport(void) appendStringInfo(&logbuf, _("Process %d: %s"), info->pid, - pgstat_get_backend_current_activity(info->pid, false)); + bestatus_get_backend_current_activity(info->pid, false)); } pgstat_report_deadlock(); diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c index c46bb8d057..01597d1f93 100644 --- a/src/backend/storage/lmgr/lwlock.c +++ b/src/backend/storage/lmgr/lwlock.c @@ -76,8 +76,8 @@ */ #include "postgres.h" +#include "bestatus.h" #include "miscadmin.h" -#include "pgstat.h" #include "pg_trace.h" #include "postmaster/postmaster.h" #include "replication/slot.h" @@ -697,7 +697,7 @@ LWLockInitialize(LWLock *lock, int tranche_id) static inline void LWLockReportWaitStart(LWLock *lock) { - pgstat_report_wait_start(PG_WAIT_LWLOCK | lock->tranche); + bestatus_report_wait_start(PG_WAIT_LWLOCK | lock->tranche); } /* @@ -706,7 +706,7 @@ LWLockReportWaitStart(LWLock *lock) static inline void LWLockReportWaitEnd(void) { - pgstat_report_wait_end(); + bestatus_report_wait_end(); } /* diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c index e8390311d0..ac352885f3 100644 --- a/src/backend/storage/lmgr/predicate.c +++ b/src/backend/storage/lmgr/predicate.c @@ -193,8 +193,8 @@ #include "access/twophase_rmgr.h" #include "access/xact.h" #include "access/xlog.h" +#include "bestatus.h" #include "miscadmin.h" -#include "pgstat.h" #include "storage/bufmgr.h" #include "storage/predicate.h" #include "storage/predicate_internals.h" diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 6f9aaa52fa..0ecaa24b1a 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -38,8 +38,8 @@ #include "access/transam.h" #include "access/twophase.h" #include "access/xact.h" +#include "bestatus.h" #include "miscadmin.h" -#include "pgstat.h" #include "postmaster/autovacuum.h" #include "replication/slot.h" #include "replication/syncrep.h" diff --git a/src/backend/storage/smgr/md.c b/src/backend/storage/smgr/md.c index f4374d077b..625e50e129 100644 --- a/src/backend/storage/smgr/md.c +++ b/src/backend/storage/smgr/md.c @@ -28,7 +28,7 @@ #include "miscadmin.h" #include "access/xlogutils.h" #include "access/xlog.h" -#include "pgstat.h" +#include "bestatus.h" #include "portability/instr_time.h" #include "postmaster/bgwriter.h" #include "storage/fd.h" diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index ee4e43331b..16148a3298 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -39,6 +39,7 @@ #include "access/parallel.h" #include "access/printtup.h" #include "access/xact.h" +#include "bestatus.h" #include "catalog/pg_type.h" #include "commands/async.h" #include "commands/prepare.h" @@ -997,7 +998,7 @@ exec_simple_query(const char *query_string) */ debug_query_string = query_string; - pgstat_report_activity(STATE_RUNNING, query_string); + bestatus_report_activity(STATE_RUNNING, query_string); TRACE_POSTGRESQL_QUERY_START(query_string); @@ -1332,7 +1333,7 @@ exec_parse_message(const char *query_string, /* string to execute */ */ debug_query_string = query_string; - pgstat_report_activity(STATE_RUNNING, query_string); + bestatus_report_activity(STATE_RUNNING, query_string); set_ps_display("PARSE", false); @@ -1625,7 +1626,7 @@ exec_bind_message(StringInfo input_message) */ debug_query_string = psrc->query_string; - pgstat_report_activity(STATE_RUNNING, psrc->query_string); + bestatus_report_activity(STATE_RUNNING, psrc->query_string); set_ps_display("BIND", false); @@ -2027,7 +2028,7 @@ exec_execute_message(const char *portal_name, long max_rows) */ debug_query_string = sourceText; - pgstat_report_activity(STATE_RUNNING, sourceText); + bestatus_report_activity(STATE_RUNNING, sourceText); set_ps_display(portal->commandTag, false); @@ -4142,7 +4143,7 @@ PostgresMain(int argc, char *argv[], if (IsAbortedTransactionBlockState()) { set_ps_display("idle in transaction (aborted)", false); - pgstat_report_activity(STATE_IDLEINTRANSACTION_ABORTED, NULL); + bestatus_report_activity(STATE_IDLEINTRANSACTION_ABORTED, NULL); /* Start the idle-in-transaction timer */ if (IdleInTransactionSessionTimeout > 0) @@ -4155,7 +4156,7 @@ PostgresMain(int argc, char *argv[], else if (IsTransactionOrTransactionBlock()) { set_ps_display("idle in transaction", false); - pgstat_report_activity(STATE_IDLEINTRANSACTION, NULL); + bestatus_report_activity(STATE_IDLEINTRANSACTION, NULL); /* Start the idle-in-transaction timer */ if (IdleInTransactionSessionTimeout > 0) @@ -4179,7 +4180,7 @@ PostgresMain(int argc, char *argv[], stats_timeout); } set_ps_display("idle", false); - pgstat_report_activity(STATE_IDLE, NULL); + bestatus_report_activity(STATE_IDLE, NULL); } ReadyForQuery(whereToSendOutput); @@ -4333,7 +4334,7 @@ PostgresMain(int argc, char *argv[], SetCurrentStatementStartTimestamp(); /* Report query to various monitoring facilities. */ - pgstat_report_activity(STATE_FASTPATH, NULL); + bestatus_report_activity(STATE_FASTPATH, NULL); set_ps_display("", false); /* start an xact for this function invocation */ diff --git a/src/backend/utils/adt/misc.c b/src/backend/utils/adt/misc.c index 309eb2935c..b229f42622 100644 --- a/src/backend/utils/adt/misc.c +++ b/src/backend/utils/adt/misc.c @@ -20,6 +20,7 @@ #include #include "access/sysattr.h" +#include "bestatus.h" #include "catalog/catalog.h" #include "catalog/pg_tablespace.h" #include "catalog/pg_type.h" @@ -28,7 +29,6 @@ #include "common/keywords.h" #include "funcapi.h" #include "miscadmin.h" -#include "pgstat.h" #include "parser/scansup.h" #include "postmaster/syslogger.h" #include "rewrite/rewriteHandler.h" diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c index eca801eeed..1673aeba93 100644 --- a/src/backend/utils/adt/pgstatfuncs.c +++ b/src/backend/utils/adt/pgstatfuncs.c @@ -15,6 +15,7 @@ #include "postgres.h" #include "access/htup_details.h" +#include "bestatus.h" #include "catalog/pg_authid.h" #include "catalog/pg_type.h" #include "common/ip.h" @@ -411,7 +412,7 @@ pg_stat_get_backend_idset(PG_FUNCTION_ARGS) funcctx->user_fctx = fctx; fctx[0] = 0; - fctx[1] = pgstat_fetch_stat_numbackends(); + fctx[1] = bestatus_fetch_stat_numbackends(); } /* stuff done on every call of the function */ @@ -439,8 +440,8 @@ pg_stat_get_backend_idset(PG_FUNCTION_ARGS) Datum pg_stat_get_progress_info(PG_FUNCTION_ARGS) { -#define PG_STAT_GET_PROGRESS_COLS PGSTAT_NUM_PROGRESS_PARAM + 3 - int num_backends = pgstat_fetch_stat_numbackends(); +#define PG_STAT_GET_PROGRESS_COLS BESTATUS_NUM_PROGRESS_PARAM + 3 + int num_backends = bestatus_fetch_stat_numbackends(); int curr_backend; char *cmd = text_to_cstring(PG_GETARG_TEXT_PP(0)); ProgressCommandType cmdtype; @@ -494,7 +495,7 @@ pg_stat_get_progress_info(PG_FUNCTION_ARGS) MemSet(values, 0, sizeof(values)); MemSet(nulls, 0, sizeof(nulls)); - local_beentry = pgstat_fetch_stat_local_beentry(curr_backend); + local_beentry = bestatus_fetch_stat_local_beentry(curr_backend); if (!local_beentry) continue; @@ -516,13 +517,13 @@ pg_stat_get_progress_info(PG_FUNCTION_ARGS) if (has_privs_of_role(GetUserId(), beentry->st_userid)) { values[2] = ObjectIdGetDatum(beentry->st_progress_command_target); - for (i = 0; i < PGSTAT_NUM_PROGRESS_PARAM; i++) + for (i = 0; i < BESTATUS_NUM_PROGRESS_PARAM; i++) values[i + 3] = Int64GetDatum(beentry->st_progress_param[i]); } else { nulls[2] = true; - for (i = 0; i < PGSTAT_NUM_PROGRESS_PARAM; i++) + for (i = 0; i < BESTATUS_NUM_PROGRESS_PARAM; i++) nulls[i + 3] = true; } @@ -542,7 +543,7 @@ Datum pg_stat_get_activity(PG_FUNCTION_ARGS) { #define PG_STAT_GET_ACTIVITY_COLS 24 - int num_backends = pgstat_fetch_stat_numbackends(); + int num_backends = bestatus_fetch_stat_numbackends(); int curr_backend; int pid = PG_ARGISNULL(0) ? -1 : PG_GETARG_INT32(0); ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo; @@ -592,7 +593,7 @@ pg_stat_get_activity(PG_FUNCTION_ARGS) MemSet(nulls, 0, sizeof(nulls)); /* Get the next one in the list */ - local_beentry = pgstat_fetch_stat_local_beentry(curr_backend); + local_beentry = bestatus_fetch_stat_local_beentry(curr_backend); if (!local_beentry) { int i; @@ -692,7 +693,7 @@ pg_stat_get_activity(PG_FUNCTION_ARGS) break; } - clipped_activity = pgstat_clip_activity(beentry->st_activity_raw); + clipped_activity = bestatus_clip_activity(beentry->st_activity_raw); values[5] = CStringGetTextDatum(clipped_activity); pfree(clipped_activity); @@ -702,8 +703,8 @@ pg_stat_get_activity(PG_FUNCTION_ARGS) uint32 raw_wait_event; raw_wait_event = UINT32_ACCESS_ONCE(proc->wait_event_info); - wait_event_type = pgstat_get_wait_event_type(raw_wait_event); - wait_event = pgstat_get_wait_event(raw_wait_event); + wait_event_type = bestatus_get_wait_event_type(raw_wait_event); + wait_event = bestatus_get_wait_event(raw_wait_event); } else if (beentry->st_backendType != B_BACKEND) @@ -721,8 +722,8 @@ pg_stat_get_activity(PG_FUNCTION_ARGS) raw_wait_event = UINT32_ACCESS_ONCE(proc->wait_event_info); wait_event_type = - pgstat_get_wait_event_type(raw_wait_event); - wait_event = pgstat_get_wait_event(raw_wait_event); + bestatus_get_wait_event_type(raw_wait_event); + wait_event = bestatus_get_wait_event(raw_wait_event); } } @@ -836,7 +837,7 @@ pg_stat_get_activity(PG_FUNCTION_ARGS) } else values[17] = - CStringGetTextDatum(pgstat_get_backend_desc(beentry->st_backendType)); + CStringGetTextDatum(bestatus_get_backend_desc(beentry->st_backendType)); } else { @@ -882,7 +883,7 @@ pg_stat_get_backend_pid(PG_FUNCTION_ARGS) int32 beid = PG_GETARG_INT32(0); PgBackendStatus *beentry; - if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL) + if ((beentry = bestatus_fetch_stat_beentry(beid)) == NULL) PG_RETURN_NULL(); PG_RETURN_INT32(beentry->st_procpid); @@ -895,7 +896,7 @@ pg_stat_get_backend_dbid(PG_FUNCTION_ARGS) int32 beid = PG_GETARG_INT32(0); PgBackendStatus *beentry; - if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL) + if ((beentry = bestatus_fetch_stat_beentry(beid)) == NULL) PG_RETURN_NULL(); PG_RETURN_OID(beentry->st_databaseid); @@ -908,7 +909,7 @@ pg_stat_get_backend_userid(PG_FUNCTION_ARGS) int32 beid = PG_GETARG_INT32(0); PgBackendStatus *beentry; - if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL) + if ((beentry = bestatus_fetch_stat_beentry(beid)) == NULL) PG_RETURN_NULL(); PG_RETURN_OID(beentry->st_userid); @@ -924,7 +925,7 @@ pg_stat_get_backend_activity(PG_FUNCTION_ARGS) char *clipped_activity; text *ret; - if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL) + if ((beentry = bestatus_fetch_stat_beentry(beid)) == NULL) activity = ""; else if (!has_privs_of_role(GetUserId(), beentry->st_userid)) activity = ""; @@ -933,7 +934,7 @@ pg_stat_get_backend_activity(PG_FUNCTION_ARGS) else activity = beentry->st_activity_raw; - clipped_activity = pgstat_clip_activity(activity); + clipped_activity = bestatus_clip_activity(activity); ret = cstring_to_text(activity); pfree(clipped_activity); @@ -948,12 +949,12 @@ pg_stat_get_backend_wait_event_type(PG_FUNCTION_ARGS) PGPROC *proc; const char *wait_event_type = NULL; - if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL) + if ((beentry = bestatus_fetch_stat_beentry(beid)) == NULL) wait_event_type = ""; else if (!has_privs_of_role(GetUserId(), beentry->st_userid)) wait_event_type = ""; else if ((proc = BackendPidGetProc(beentry->st_procpid)) != NULL) - wait_event_type = pgstat_get_wait_event_type(proc->wait_event_info); + wait_event_type = bestatus_get_wait_event_type(proc->wait_event_info); if (!wait_event_type) PG_RETURN_NULL(); @@ -969,12 +970,12 @@ pg_stat_get_backend_wait_event(PG_FUNCTION_ARGS) PGPROC *proc; const char *wait_event = NULL; - if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL) + if ((beentry = bestatus_fetch_stat_beentry(beid)) == NULL) wait_event = ""; else if (!has_privs_of_role(GetUserId(), beentry->st_userid)) wait_event = ""; else if ((proc = BackendPidGetProc(beentry->st_procpid)) != NULL) - wait_event = pgstat_get_wait_event(proc->wait_event_info); + wait_event = bestatus_get_wait_event(proc->wait_event_info); if (!wait_event) PG_RETURN_NULL(); @@ -990,7 +991,7 @@ pg_stat_get_backend_activity_start(PG_FUNCTION_ARGS) TimestampTz result; PgBackendStatus *beentry; - if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL) + if ((beentry = bestatus_fetch_stat_beentry(beid)) == NULL) PG_RETURN_NULL(); if (!has_privs_of_role(GetUserId(), beentry->st_userid)) @@ -1016,7 +1017,7 @@ pg_stat_get_backend_xact_start(PG_FUNCTION_ARGS) TimestampTz result; PgBackendStatus *beentry; - if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL) + if ((beentry = bestatus_fetch_stat_beentry(beid)) == NULL) PG_RETURN_NULL(); if (!has_privs_of_role(GetUserId(), beentry->st_userid)) @@ -1038,7 +1039,7 @@ pg_stat_get_backend_start(PG_FUNCTION_ARGS) TimestampTz result; PgBackendStatus *beentry; - if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL) + if ((beentry = bestatus_fetch_stat_beentry(beid)) == NULL) PG_RETURN_NULL(); if (!has_privs_of_role(GetUserId(), beentry->st_userid)) @@ -1062,7 +1063,7 @@ pg_stat_get_backend_client_addr(PG_FUNCTION_ARGS) char remote_host[NI_MAXHOST]; int ret; - if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL) + if ((beentry = bestatus_fetch_stat_beentry(beid)) == NULL) PG_RETURN_NULL(); if (!has_privs_of_role(GetUserId(), beentry->st_userid)) @@ -1109,7 +1110,7 @@ pg_stat_get_backend_client_port(PG_FUNCTION_ARGS) char remote_port[NI_MAXSERV]; int ret; - if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL) + if ((beentry = bestatus_fetch_stat_beentry(beid)) == NULL) PG_RETURN_NULL(); if (!has_privs_of_role(GetUserId(), beentry->st_userid)) @@ -1153,13 +1154,13 @@ pg_stat_get_db_numbackends(PG_FUNCTION_ARGS) { Oid dbid = PG_GETARG_OID(0); int32 result; - int tot_backends = pgstat_fetch_stat_numbackends(); + int tot_backends = bestatus_fetch_stat_numbackends(); int beid; result = 0; for (beid = 1; beid <= tot_backends; beid++) { - PgBackendStatus *beentry = pgstat_fetch_stat_beentry(beid); + PgBackendStatus *beentry = bestatus_fetch_stat_beentry(beid); if (beentry && beentry->st_databaseid == dbid) result++; diff --git a/src/backend/utils/cache/relmapper.c b/src/backend/utils/cache/relmapper.c index 905867dc76..3303d9ce35 100644 --- a/src/backend/utils/cache/relmapper.c +++ b/src/backend/utils/cache/relmapper.c @@ -46,11 +46,11 @@ #include "access/xact.h" #include "access/xlog.h" #include "access/xloginsert.h" +#include "bestatus.h" #include "catalog/catalog.h" #include "catalog/pg_tablespace.h" #include "catalog/storage.h" #include "miscadmin.h" -#include "pgstat.h" #include "storage/fd.h" #include "storage/lwlock.h" #include "utils/inval.h" @@ -731,7 +731,7 @@ load_relmap_file(bool shared) * look, the sinval signaling mechanism will make us re-read it before we * are able to access any relation that's affected by the change. */ - pgstat_report_wait_start(WAIT_EVENT_RELATION_MAP_READ); + bestatus_report_wait_start(WAIT_EVENT_RELATION_MAP_READ); r = read(fd, map, sizeof(RelMapFile)); if (r != sizeof(RelMapFile)) { @@ -745,7 +745,7 @@ load_relmap_file(bool shared) errmsg("could not read file \"%s\": read %d of %zu", mapfilename, r, sizeof(RelMapFile)))); } - pgstat_report_wait_end(); + bestatus_report_wait_end(); CloseTransientFile(fd); @@ -855,7 +855,7 @@ write_relmap_file(bool shared, RelMapFile *newmap, } errno = 0; - pgstat_report_wait_start(WAIT_EVENT_RELATION_MAP_WRITE); + bestatus_report_wait_start(WAIT_EVENT_RELATION_MAP_WRITE); if (write(fd, newmap, sizeof(RelMapFile)) != sizeof(RelMapFile)) { /* if write didn't set errno, assume problem is no disk space */ @@ -866,7 +866,7 @@ write_relmap_file(bool shared, RelMapFile *newmap, errmsg("could not write file \"%s\": %m", mapfilename))); } - pgstat_report_wait_end(); + bestatus_report_wait_end(); /* * We choose to fsync the data to disk before considering the task done. @@ -874,13 +874,13 @@ write_relmap_file(bool shared, RelMapFile *newmap, * issue, but it would complicate checkpointing --- see notes for * CheckPointRelationMap. */ - pgstat_report_wait_start(WAIT_EVENT_RELATION_MAP_SYNC); + bestatus_report_wait_start(WAIT_EVENT_RELATION_MAP_SYNC); if (pg_fsync(fd) != 0) ereport(ERROR, (errcode_for_file_access(), errmsg("could not fsync file \"%s\": %m", mapfilename))); - pgstat_report_wait_end(); + bestatus_report_wait_end(); if (CloseTransientFile(fd)) ereport(ERROR, diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c index 238fe1deec..a00e5618f2 100644 --- a/src/backend/utils/init/miscinit.c +++ b/src/backend/utils/init/miscinit.c @@ -31,12 +31,12 @@ #endif #include "access/htup_details.h" +#include "bestatus.h" #include "catalog/pg_authid.h" #include "common/file_perm.h" #include "libpq/libpq.h" #include "mb/pg_wchar.h" #include "miscadmin.h" -#include "pgstat.h" #include "postmaster/autovacuum.h" #include "postmaster/postmaster.h" #include "storage/fd.h" @@ -961,13 +961,13 @@ CreateLockFile(const char *filename, bool amPostmaster, errmsg("could not open lock file \"%s\": %m", filename))); } - pgstat_report_wait_start(WAIT_EVENT_LOCK_FILE_CREATE_READ); + bestatus_report_wait_start(WAIT_EVENT_LOCK_FILE_CREATE_READ); if ((len = read(fd, buffer, sizeof(buffer) - 1)) < 0) ereport(FATAL, (errcode_for_file_access(), errmsg("could not read lock file \"%s\": %m", filename))); - pgstat_report_wait_end(); + bestatus_report_wait_end(); close(fd); if (len == 0) @@ -1113,7 +1113,7 @@ CreateLockFile(const char *filename, bool amPostmaster, strlcat(buffer, "\n", sizeof(buffer)); errno = 0; - pgstat_report_wait_start(WAIT_EVENT_LOCK_FILE_CREATE_WRITE); + bestatus_report_wait_start(WAIT_EVENT_LOCK_FILE_CREATE_WRITE); if (write(fd, buffer, strlen(buffer)) != strlen(buffer)) { int save_errno = errno; @@ -1126,9 +1126,9 @@ CreateLockFile(const char *filename, bool amPostmaster, (errcode_for_file_access(), errmsg("could not write lock file \"%s\": %m", filename))); } - pgstat_report_wait_end(); + bestatus_report_wait_end(); - pgstat_report_wait_start(WAIT_EVENT_LOCK_FILE_CREATE_SYNC); + bestatus_report_wait_start(WAIT_EVENT_LOCK_FILE_CREATE_SYNC); if (pg_fsync(fd) != 0) { int save_errno = errno; @@ -1140,7 +1140,7 @@ CreateLockFile(const char *filename, bool amPostmaster, (errcode_for_file_access(), errmsg("could not write lock file \"%s\": %m", filename))); } - pgstat_report_wait_end(); + bestatus_report_wait_end(); if (close(fd) != 0) { int save_errno = errno; @@ -1274,9 +1274,9 @@ AddToDataDirLockFile(int target_line, const char *str) DIRECTORY_LOCK_FILE))); return; } - pgstat_report_wait_start(WAIT_EVENT_LOCK_FILE_ADDTODATADIR_READ); + bestatus_report_wait_start(WAIT_EVENT_LOCK_FILE_ADDTODATADIR_READ); len = read(fd, srcbuffer, sizeof(srcbuffer) - 1); - pgstat_report_wait_end(); + bestatus_report_wait_end(); if (len < 0) { ereport(LOG, @@ -1336,11 +1336,11 @@ AddToDataDirLockFile(int target_line, const char *str) */ len = strlen(destbuffer); errno = 0; - pgstat_report_wait_start(WAIT_EVENT_LOCK_FILE_ADDTODATADIR_WRITE); + bestatus_report_wait_start(WAIT_EVENT_LOCK_FILE_ADDTODATADIR_WRITE); if (lseek(fd, (off_t) 0, SEEK_SET) != 0 || (int) write(fd, destbuffer, len) != len) { - pgstat_report_wait_end(); + bestatus_report_wait_end(); /* if write didn't set errno, assume problem is no disk space */ if (errno == 0) errno = ENOSPC; @@ -1351,8 +1351,8 @@ AddToDataDirLockFile(int target_line, const char *str) close(fd); return; } - pgstat_report_wait_end(); - pgstat_report_wait_start(WAIT_EVENT_LOCK_FILE_ADDTODATADIR_SYNC); + bestatus_report_wait_end(); + bestatus_report_wait_start(WAIT_EVENT_LOCK_FILE_ADDTODATADIR_SYNC); if (pg_fsync(fd) != 0) { ereport(LOG, @@ -1360,7 +1360,7 @@ AddToDataDirLockFile(int target_line, const char *str) errmsg("could not write to file \"%s\": %m", DIRECTORY_LOCK_FILE))); } - pgstat_report_wait_end(); + bestatus_report_wait_end(); if (close(fd) != 0) { ereport(LOG, @@ -1417,9 +1417,9 @@ RecheckDataDirLockFile(void) return true; } } - pgstat_report_wait_start(WAIT_EVENT_LOCK_FILE_RECHECKDATADIR_READ); + bestatus_report_wait_start(WAIT_EVENT_LOCK_FILE_RECHECKDATADIR_READ); len = read(fd, buffer, sizeof(buffer) - 1); - pgstat_report_wait_end(); + bestatus_report_wait_end(); if (len < 0) { ereport(LOG, diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c index 1e4fa89135..9465c7d624 100644 --- a/src/backend/utils/init/postinit.c +++ b/src/backend/utils/init/postinit.c @@ -25,6 +25,7 @@ #include "access/sysattr.h" #include "access/xact.h" #include "access/xlog.h" +#include "bestatus.h" #include "catalog/catalog.h" #include "catalog/indexing.h" #include "catalog/namespace.h" @@ -688,7 +689,10 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username, /* Initialize stats collection --- must happen before first xact */ if (!bootstrap) + { pgstat_initialize(); + bestatus_initialize(); + } /* * Load relcache entries for the shared system catalogs. This must create @@ -710,7 +714,7 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username, if (IsAutoVacuumLauncherProcess()) { /* report this backend in the PgBackendStatus array */ - pgstat_bestart(); + bestatus_bestart(); return; } @@ -857,7 +861,7 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username, InitializeClientEncoding(); /* report this backend in the PgBackendStatus array */ - pgstat_bestart(); + bestatus_bestart(); /* close the transaction we started above */ CommitTransactionCommand(); @@ -923,7 +927,7 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username, */ if (!bootstrap) { - pgstat_bestart(); + bestatus_bestart(); CommitTransactionCommand(); } return; @@ -1075,7 +1079,7 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username, /* report this backend in the PgBackendStatus array */ if (!bootstrap) - pgstat_bestart(); + bestatus_bestart(); /* close the transaction we started above */ if (!bootstrap) diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 37f3389bd0..36e84a13e8 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -33,6 +33,7 @@ #include "access/twophase.h" #include "access/xact.h" #include "access/xlog_internal.h" +#include "bestatus.h" #include "catalog/namespace.h" #include "catalog/pg_authid.h" #include "commands/async.h" @@ -1291,7 +1292,7 @@ static struct config_bool ConfigureNamesBool[] = "executing command of each session, along with " "the time at which that command began execution.") }, - &pgstat_track_activities, + &bestatus_track_activities, true, NULL, NULL, NULL }, @@ -3048,7 +3049,7 @@ static struct config_int ConfigureNamesInt[] = NULL, GUC_UNIT_BYTE }, - &pgstat_track_activity_query_size, + &bestatus_track_activity_query_size, 1024, 100, 102400, NULL, NULL, NULL }, @@ -10728,7 +10729,7 @@ static void assign_application_name(const char *newval, void *extra) { /* Update the pg_stat_activity view */ - pgstat_report_appname(newval); + bestatus_report_appname(newval); } static bool diff --git a/src/include/bestatus.h b/src/include/bestatus.h new file mode 100644 index 0000000000..72b3e9f5f1 --- /dev/null +++ b/src/include/bestatus.h @@ -0,0 +1,545 @@ +/* ---------- + * bestatus.h + * + * Definitions for the PostgreSQL backend status monitor facility + * + * Copyright (c) 2001-2018, PostgreSQL Global Development Group + * + * src/include/bestatus.h + * ---------- + */ +#ifndef BESTATUS_H +#define BESTATUS_H + +#include "datatype/timestamp.h" +#include "libpq/pqcomm.h" +#include "storage/proc.h" + +/* ---------- + * Backend types + * ---------- + */ +typedef enum BackendType +{ + B_AUTOVAC_LAUNCHER, + B_AUTOVAC_WORKER, + B_BACKEND, + B_BG_WORKER, + B_BG_WRITER, + B_CHECKPOINTER, + B_STARTUP, + B_WAL_RECEIVER, + B_WAL_SENDER, + B_WAL_WRITER, + B_ARCHIVER +} BackendType; + + +/* ---------- + * Backend states + * ---------- + */ +typedef enum BackendState +{ + STATE_UNDEFINED, + STATE_IDLE, + STATE_RUNNING, + STATE_IDLEINTRANSACTION, + STATE_FASTPATH, + STATE_IDLEINTRANSACTION_ABORTED, + STATE_DISABLED +} BackendState; + + +/* ---------- + * Wait Classes + * ---------- + */ +#define PG_WAIT_LWLOCK 0x01000000U +#define PG_WAIT_LOCK 0x03000000U +#define PG_WAIT_BUFFER_PIN 0x04000000U +#define PG_WAIT_ACTIVITY 0x05000000U +#define PG_WAIT_CLIENT 0x06000000U +#define PG_WAIT_EXTENSION 0x07000000U +#define PG_WAIT_IPC 0x08000000U +#define PG_WAIT_TIMEOUT 0x09000000U +#define PG_WAIT_IO 0x0A000000U + +/* ---------- + * Wait Events - Activity + * + * Use this category when a process is waiting because it has no work to do, + * unless the "Client" or "Timeout" category describes the situation better. + * Typically, this should only be used for background processes. + * ---------- + */ +typedef enum +{ + WAIT_EVENT_ARCHIVER_MAIN = PG_WAIT_ACTIVITY, + WAIT_EVENT_AUTOVACUUM_MAIN, + WAIT_EVENT_BGWRITER_HIBERNATE, + WAIT_EVENT_BGWRITER_MAIN, + WAIT_EVENT_CHECKPOINTER_MAIN, + WAIT_EVENT_LOGICAL_APPLY_MAIN, + WAIT_EVENT_LOGICAL_LAUNCHER_MAIN, + WAIT_EVENT_BESTATUS_MAIN, + WAIT_EVENT_RECOVERY_WAL_ALL, + WAIT_EVENT_RECOVERY_WAL_STREAM, + WAIT_EVENT_SYSLOGGER_MAIN, + WAIT_EVENT_WAL_RECEIVER_MAIN, + WAIT_EVENT_WAL_SENDER_MAIN, + WAIT_EVENT_WAL_WRITER_MAIN +} WaitEventActivity; + +/* ---------- + * Wait Events - Client + * + * Use this category when a process is waiting to send data to or receive data + * from the frontend process to which it is connected. This is never used for + * a background process, which has no client connection. + * ---------- + */ +typedef enum +{ + WAIT_EVENT_CLIENT_READ = PG_WAIT_CLIENT, + WAIT_EVENT_CLIENT_WRITE, + WAIT_EVENT_LIBPQWALRECEIVER_CONNECT, + WAIT_EVENT_LIBPQWALRECEIVER_RECEIVE, + WAIT_EVENT_SSL_OPEN_SERVER, + WAIT_EVENT_WAL_RECEIVER_WAIT_START, + WAIT_EVENT_WAL_SENDER_WAIT_WAL, + WAIT_EVENT_WAL_SENDER_WRITE_DATA +} WaitEventClient; + +/* ---------- + * Wait Events - IPC + * + * Use this category when a process cannot complete the work it is doing because + * it is waiting for a notification from another process. + * ---------- + */ +typedef enum +{ + WAIT_EVENT_BGWORKER_SHUTDOWN = PG_WAIT_IPC, + WAIT_EVENT_BGWORKER_STARTUP, + WAIT_EVENT_BTREE_PAGE, + WAIT_EVENT_CLOG_GROUP_UPDATE, + WAIT_EVENT_EXECUTE_GATHER, + WAIT_EVENT_HASH_BATCH_ALLOCATING, + WAIT_EVENT_HASH_BATCH_ELECTING, + WAIT_EVENT_HASH_BATCH_LOADING, + WAIT_EVENT_HASH_BUILD_ALLOCATING, + WAIT_EVENT_HASH_BUILD_ELECTING, + WAIT_EVENT_HASH_BUILD_HASHING_INNER, + WAIT_EVENT_HASH_BUILD_HASHING_OUTER, + WAIT_EVENT_HASH_GROW_BATCHES_ALLOCATING, + WAIT_EVENT_HASH_GROW_BATCHES_DECIDING, + WAIT_EVENT_HASH_GROW_BATCHES_ELECTING, + WAIT_EVENT_HASH_GROW_BATCHES_FINISHING, + WAIT_EVENT_HASH_GROW_BATCHES_REPARTITIONING, + WAIT_EVENT_HASH_GROW_BUCKETS_ALLOCATING, + WAIT_EVENT_HASH_GROW_BUCKETS_ELECTING, + WAIT_EVENT_HASH_GROW_BUCKETS_REINSERTING, + WAIT_EVENT_LOGICAL_SYNC_DATA, + WAIT_EVENT_LOGICAL_SYNC_STATE_CHANGE, + WAIT_EVENT_MQ_INTERNAL, + WAIT_EVENT_MQ_PUT_MESSAGE, + WAIT_EVENT_MQ_RECEIVE, + WAIT_EVENT_MQ_SEND, + WAIT_EVENT_PARALLEL_BITMAP_SCAN, + WAIT_EVENT_PARALLEL_CREATE_INDEX_SCAN, + WAIT_EVENT_PARALLEL_FINISH, + WAIT_EVENT_PROCARRAY_GROUP_UPDATE, + WAIT_EVENT_PROMOTE, + WAIT_EVENT_REPLICATION_ORIGIN_DROP, + WAIT_EVENT_REPLICATION_SLOT_DROP, + WAIT_EVENT_SAFE_SNAPSHOT, + WAIT_EVENT_SYNC_REP +} WaitEventIPC; + +/* ---------- + * Wait Events - Timeout + * + * Use this category when a process is waiting for a timeout to expire. + * ---------- + */ +typedef enum +{ + WAIT_EVENT_BASE_BACKUP_THROTTLE = PG_WAIT_TIMEOUT, + WAIT_EVENT_PG_SLEEP, + WAIT_EVENT_RECOVERY_APPLY_DELAY +} WaitEventTimeout; + +/* ---------- + * Wait Events - IO + * + * Use this category when a process is waiting for a IO. + * ---------- + */ +typedef enum +{ + WAIT_EVENT_BUFFILE_READ = PG_WAIT_IO, + WAIT_EVENT_BUFFILE_WRITE, + WAIT_EVENT_CONTROL_FILE_READ, + WAIT_EVENT_CONTROL_FILE_SYNC, + WAIT_EVENT_CONTROL_FILE_SYNC_UPDATE, + WAIT_EVENT_CONTROL_FILE_WRITE, + WAIT_EVENT_CONTROL_FILE_WRITE_UPDATE, + WAIT_EVENT_COPY_FILE_READ, + WAIT_EVENT_COPY_FILE_WRITE, + WAIT_EVENT_DATA_FILE_EXTEND, + WAIT_EVENT_DATA_FILE_FLUSH, + WAIT_EVENT_DATA_FILE_IMMEDIATE_SYNC, + WAIT_EVENT_DATA_FILE_PREFETCH, + WAIT_EVENT_DATA_FILE_READ, + WAIT_EVENT_DATA_FILE_SYNC, + WAIT_EVENT_DATA_FILE_TRUNCATE, + WAIT_EVENT_DATA_FILE_WRITE, + WAIT_EVENT_DSM_FILL_ZERO_WRITE, + WAIT_EVENT_LOCK_FILE_ADDTODATADIR_READ, + WAIT_EVENT_LOCK_FILE_ADDTODATADIR_SYNC, + WAIT_EVENT_LOCK_FILE_ADDTODATADIR_WRITE, + WAIT_EVENT_LOCK_FILE_CREATE_READ, + WAIT_EVENT_LOCK_FILE_CREATE_SYNC, + WAIT_EVENT_LOCK_FILE_CREATE_WRITE, + WAIT_EVENT_LOCK_FILE_RECHECKDATADIR_READ, + WAIT_EVENT_LOGICAL_REWRITE_CHECKPOINT_SYNC, + WAIT_EVENT_LOGICAL_REWRITE_MAPPING_SYNC, + WAIT_EVENT_LOGICAL_REWRITE_MAPPING_WRITE, + WAIT_EVENT_LOGICAL_REWRITE_SYNC, + WAIT_EVENT_LOGICAL_REWRITE_TRUNCATE, + WAIT_EVENT_LOGICAL_REWRITE_WRITE, + WAIT_EVENT_RELATION_MAP_READ, + WAIT_EVENT_RELATION_MAP_SYNC, + WAIT_EVENT_RELATION_MAP_WRITE, + WAIT_EVENT_REORDER_BUFFER_READ, + WAIT_EVENT_REORDER_BUFFER_WRITE, + WAIT_EVENT_REORDER_LOGICAL_MAPPING_READ, + WAIT_EVENT_REPLICATION_SLOT_READ, + WAIT_EVENT_REPLICATION_SLOT_RESTORE_SYNC, + WAIT_EVENT_REPLICATION_SLOT_SYNC, + WAIT_EVENT_REPLICATION_SLOT_WRITE, + WAIT_EVENT_SLRU_FLUSH_SYNC, + WAIT_EVENT_SLRU_READ, + WAIT_EVENT_SLRU_SYNC, + WAIT_EVENT_SLRU_WRITE, + WAIT_EVENT_SNAPBUILD_READ, + WAIT_EVENT_SNAPBUILD_SYNC, + WAIT_EVENT_SNAPBUILD_WRITE, + WAIT_EVENT_TIMELINE_HISTORY_FILE_SYNC, + WAIT_EVENT_TIMELINE_HISTORY_FILE_WRITE, + WAIT_EVENT_TIMELINE_HISTORY_READ, + WAIT_EVENT_TIMELINE_HISTORY_SYNC, + WAIT_EVENT_TIMELINE_HISTORY_WRITE, + WAIT_EVENT_TWOPHASE_FILE_READ, + WAIT_EVENT_TWOPHASE_FILE_SYNC, + WAIT_EVENT_TWOPHASE_FILE_WRITE, + WAIT_EVENT_WALSENDER_TIMELINE_HISTORY_READ, + WAIT_EVENT_WAL_BOOTSTRAP_SYNC, + WAIT_EVENT_WAL_BOOTSTRAP_WRITE, + WAIT_EVENT_WAL_COPY_READ, + WAIT_EVENT_WAL_COPY_SYNC, + WAIT_EVENT_WAL_COPY_WRITE, + WAIT_EVENT_WAL_INIT_SYNC, + WAIT_EVENT_WAL_INIT_WRITE, + WAIT_EVENT_WAL_READ, + WAIT_EVENT_WAL_SYNC, + WAIT_EVENT_WAL_SYNC_METHOD_ASSIGN, + WAIT_EVENT_WAL_WRITE +} WaitEventIO; + +/* ---------- + * Command type for progress reporting purposes + * ---------- + */ +typedef enum ProgressCommandType +{ + PROGRESS_COMMAND_INVALID, + PROGRESS_COMMAND_VACUUM +} ProgressCommandType; + +#define BESTATUS_NUM_PROGRESS_PARAM 10 + +/* ---------- + * Shared-memory data structures + * ---------- + */ + + +/* + * PgBackendSSLStatus + * + * For each backend, we keep the SSL status in a separate struct, that + * is only filled in if SSL is enabled. + */ +typedef struct PgBackendSSLStatus +{ + /* Information about SSL connection */ + int ssl_bits; + bool ssl_compression; + char ssl_version[NAMEDATALEN]; /* MUST be null-terminated */ + char ssl_cipher[NAMEDATALEN]; /* MUST be null-terminated */ + char ssl_clientdn[NAMEDATALEN]; /* MUST be null-terminated */ +} PgBackendSSLStatus; + + +/* ---------- + * PgBackendStatus + * + * Each live backend maintains a PgBackendStatus struct in shared memory + * showing its current activity. (The structs are allocated according to + * BackendId, but that is not critical.) Note that the collector process + * has no involvement in, or even access to, these structs. + * + * Each auxiliary process also maintains a PgBackendStatus struct in shared + * memory. + * ---------- + */ +typedef struct PgBackendStatus +{ + /* + * To avoid locking overhead, we use the following protocol: a backend + * increments st_changecount before modifying its entry, and again after + * finishing a modification. A would-be reader should note the value of + * st_changecount, copy the entry into private memory, then check + * st_changecount again. If the value hasn't changed, and if it's even, + * the copy is valid; otherwise start over. This makes updates cheap + * while reads are potentially expensive, but that's the tradeoff we want. + * + * The above protocol needs the memory barriers to ensure that the + * apparent order of execution is as it desires. Otherwise, for example, + * the CPU might rearrange the code so that st_changecount is incremented + * twice before the modification on a machine with weak memory ordering. + * This surprising result can lead to bugs. + */ + int st_changecount; + + /* The entry is valid iff st_procpid > 0, unused if st_procpid == 0 */ + int st_procpid; + + /* Type of backends */ + BackendType st_backendType; + + /* Times when current backend, transaction, and activity started */ + TimestampTz st_proc_start_timestamp; + TimestampTz st_xact_start_timestamp; + TimestampTz st_activity_start_timestamp; + TimestampTz st_state_start_timestamp; + + /* Database OID, owning user's OID, connection client address */ + Oid st_databaseid; + Oid st_userid; + SockAddr st_clientaddr; + char *st_clienthostname; /* MUST be null-terminated */ + + /* Information about SSL connection */ + bool st_ssl; + PgBackendSSLStatus *st_sslstatus; + + /* current state */ + BackendState st_state; + + /* application name; MUST be null-terminated */ + char *st_appname; + + /* + * Current command string; MUST be null-terminated. Note that this string + * possibly is truncated in the middle of a multi-byte character. As + * activity strings are stored more frequently than read, that allows to + * move the cost of correct truncation to the display side. Use + * bestatus_clip_activity() to truncate correctly. + */ + char *st_activity_raw; + + /* + * Command progress reporting. Any command which wishes can advertise + * that it is running by setting st_progress_command, + * st_progress_command_target, and st_progress_param[]. + * st_progress_command_target should be the OID of the relation which the + * command targets (we assume there's just one, as this is meant for + * utility commands), but the meaning of each element in the + * st_progress_param array is command-specific. + */ + ProgressCommandType st_progress_command; + Oid st_progress_command_target; + int64 st_progress_param[BESTATUS_NUM_PROGRESS_PARAM]; +} PgBackendStatus; + +/* + * Macros to load and store st_changecount with the memory barriers. + * + * bestatus_increment_changecount_before() and + * bestatus_increment_changecount_after() need to be called before and after + * PgBackendStatus entries are modified, respectively. This makes sure that + * st_changecount is incremented around the modification. + * + * Also bestatus_save_changecount_before() and bestatus_save_changecount_after() + * need to be called before and after PgBackendStatus entries are copied into + * private memory, respectively. + */ +#define bestatus_increment_changecount_before(beentry) \ + do { \ + beentry->st_changecount++; \ + pg_write_barrier(); \ + } while (0) + +#define bestatus_increment_changecount_after(beentry) \ + do { \ + pg_write_barrier(); \ + beentry->st_changecount++; \ + Assert((beentry->st_changecount & 1) == 0); \ + } while (0) + +#define bestatus_save_changecount_before(beentry, save_changecount) \ + do { \ + save_changecount = beentry->st_changecount; \ + pg_read_barrier(); \ + } while (0) + +#define bestatus_save_changecount_after(beentry, save_changecount) \ + do { \ + pg_read_barrier(); \ + save_changecount = beentry->st_changecount; \ + } while (0) + +/* ---------- + * LocalPgBackendStatus + * + * When we build the backend status array, we use LocalPgBackendStatus to be + * able to add new values to the struct when needed without adding new fields + * to the shared memory. It contains the backend status as a first member. + * ---------- + */ +typedef struct LocalPgBackendStatus +{ + /* + * Local version of the backend status entry. + */ + PgBackendStatus backendStatus; + + /* + * The xid of the current transaction if available, InvalidTransactionId + * if not. + */ + TransactionId backend_xid; + + /* + * The xmin of the current session if available, InvalidTransactionId if + * not. + */ + TransactionId backend_xmin; +} LocalPgBackendStatus; + +/* ---------- + * GUC parameters + * ---------- + */ +extern bool bestatus_track_activities; +extern PGDLLIMPORT int bestatus_track_activity_query_size; + +/* ---------- + * Functions called from backends + * ---------- + */ +extern void bestatus_clear_snapshot(void); +extern void bestatus_initialize(void); +extern void bestatus_bestart(void); + +extern const char *bestatus_get_wait_event(uint32 wait_event_info); +extern const char *bestatus_get_wait_event_type(uint32 wait_event_info); +extern const char *bestatus_get_backend_current_activity(int pid, bool checkUser); +extern const char *bestatus_get_crashed_backend_activity(int pid, char *buffer, + int buflen); +extern const char *bestatus_get_backend_desc(BackendType backendType); + +extern void bestatus_progress_start_command(ProgressCommandType cmdtype, + Oid relid); +extern void bestatus_progress_update_param(int index, int64 val); +extern void bestatus_progress_update_multi_param(int nparam, const int *index, + const int64 *val); +extern void bestatus_progress_end_command(void); + +extern char *bestatus_clip_activity(const char *raw_activity); + +/* ---------- + * bestatus_report_wait_start() - + * + * Called from places where server process needs to wait. This is called + * to report wait event information. The wait information is stored + * as 4-bytes where first byte represents the wait event class (type of + * wait, for different types of wait, refer WaitClass) and the next + * 3-bytes represent the actual wait event. Currently 2-bytes are used + * for wait event which is sufficient for current usage, 1-byte is + * reserved for future usage. + * + * NB: this *must* be able to survive being called before MyProc has been + * initialized. + * ---------- + */ +static inline void +bestatus_report_wait_start(uint32 wait_event_info) +{ + volatile PGPROC *proc = MyProc; + + if (!bestatus_track_activities || !proc) + return; + + /* + * Since this is a four-byte field which is always read and written as + * four-bytes, updates are atomic. + */ + proc->wait_event_info = wait_event_info; +} + +/* ---------- + * bestatus_report_wait_end() - + * + * Called to report end of a wait. + * + * NB: this *must* be able to survive being called before MyProc has been + * initialized. + * ---------- + */ +static inline void +bestatus_report_wait_end(void) +{ + volatile PGPROC *proc = MyProc; + + if (!bestatus_track_activities || !proc) + return; + + /* + * Since this is a four-byte field which is always read and written as + * four-bytes, updates are atomic. + */ + proc->wait_event_info = 0; +} +extern PgBackendStatus *bestatus_fetch_stat_beentry(int beid); +extern LocalPgBackendStatus *bestatus_fetch_stat_local_beentry(int beid); +extern int bestatus_fetch_stat_numbackends(void); + +/* For shared memory allocation/initialize */ +extern Size BackendStatusShmemSize(void); +extern void CreateSharedBackendStatus(void); + +void bestatus_report_xact_timestamp(TimestampTz tstamp); +void bestatus_bestat_initialize(void); + +extern void bestatus_report_activity(BackendState state, const char *cmd_str); +extern void bestatus_report_appname(const char *appname); +extern void bestatus_report_xact_timestamp(TimestampTz tstamp); +extern const char *bestatus_get_wait_event(uint32 wait_event_info); +extern const char *bestatus_get_wait_event_type(uint32 wait_event_info); +extern const char *bestatus_get_backend_current_activity(int pid, bool checkUser); +extern const char *bestatus_get_crashed_backend_activity(int pid, char *buffer, + int buflen); +extern const char *bestatus_get_backend_desc(BackendType backendType); + +extern void bestatus_progress_start_command(ProgressCommandType cmdtype, + Oid relid); +extern void bestatus_progress_update_param(int index, int64 val); +extern void bestatus_progress_update_multi_param(int nparam, const int *index, + const int64 *val); +extern void bestatus_progress_end_command(void); + +#endif /* BESTATUS_H */ diff --git a/src/include/pgstat.h b/src/include/pgstat.h index 4e51580076..4d1fc422ab 100644 --- a/src/include/pgstat.h +++ b/src/include/pgstat.h @@ -1,7 +1,7 @@ /* ---------- * pgstat.h * - * Definitions for the PostgreSQL statistics collector daemon. + * Definitions for the PostgreSQL statistics collector facility. * * Copyright (c) 2001-2018, PostgreSQL Global Development Group * @@ -14,11 +14,8 @@ #include "datatype/timestamp.h" #include "fmgr.h" #include "lib/dshash.h" -#include "libpq/pqcomm.h" -#include "port/atomics.h" #include "portability/instr_time.h" #include "postmaster/pgarch.h" -#include "storage/proc.h" #include "utils/hsearch.h" #include "utils/relcache.h" @@ -94,12 +91,11 @@ typedef enum PgStat_Single_Reset_Type RESET_FUNCTION } PgStat_Single_Reset_Type; + /* ------------------------------------------------------------ * Structures kept in backend local memory while accumulating counts * ------------------------------------------------------------ */ - - /* ---------- * PgStat_TableStatus Per-table status within a backend * @@ -167,10 +163,10 @@ typedef struct PgStat_BgWriter * PgStat_FunctionCounts The actual per-function counts kept by a backend * * This struct should contain only actual event counters, because we memcmp - * it against zeroes to detect whether there are any counts to transmit. + * it against zeroes to detect whether there are any counts to apply. * * Note that the time counters are in instr_time format here. We convert to - * microseconds in PgStat_Counter format when transmitting to the collector. + * microseconds in PgStat_Counter format when applying to shared statsitics. * ---------- */ typedef struct PgStat_FunctionCounts @@ -203,7 +199,7 @@ typedef struct PgStat_FunctionEntry } PgStat_FunctionEntry; /* ------------------------------------------------------------ - * Statistic collector data structures follow + * Statistic collector data structures on file and shared memory follow * * PGSTAT_FILE_FORMAT_ID should be changed whenever any of these * data structures change. @@ -307,7 +303,7 @@ typedef struct PgStat_StatFuncEntry /* - * Archiver statistics kept in the stats collector + * Archiver statistics kept in the shared stats */ typedef struct PgStat_ArchiverStats { @@ -323,7 +319,7 @@ typedef struct PgStat_ArchiverStats } PgStat_ArchiverStats; /* - * Global statistics kept in the stats collector + * Global statistics kept in the shared stats */ typedef struct PgStat_GlobalStats { @@ -341,422 +337,6 @@ typedef struct PgStat_GlobalStats TimestampTz stat_reset_timestamp; } PgStat_GlobalStats; - -/* ---------- - * Backend types - * ---------- - */ -typedef enum BackendType -{ - B_AUTOVAC_LAUNCHER, - B_AUTOVAC_WORKER, - B_BACKEND, - B_BG_WORKER, - B_BG_WRITER, - B_ARCHIVER, - B_CHECKPOINTER, - B_STARTUP, - B_WAL_RECEIVER, - B_WAL_SENDER, - B_WAL_WRITER -} BackendType; - - -/* ---------- - * Backend states - * ---------- - */ -typedef enum BackendState -{ - STATE_UNDEFINED, - STATE_IDLE, - STATE_RUNNING, - STATE_IDLEINTRANSACTION, - STATE_FASTPATH, - STATE_IDLEINTRANSACTION_ABORTED, - STATE_DISABLED -} BackendState; - - -/* ---------- - * Wait Classes - * ---------- - */ -#define PG_WAIT_LWLOCK 0x01000000U -#define PG_WAIT_LOCK 0x03000000U -#define PG_WAIT_BUFFER_PIN 0x04000000U -#define PG_WAIT_ACTIVITY 0x05000000U -#define PG_WAIT_CLIENT 0x06000000U -#define PG_WAIT_EXTENSION 0x07000000U -#define PG_WAIT_IPC 0x08000000U -#define PG_WAIT_TIMEOUT 0x09000000U -#define PG_WAIT_IO 0x0A000000U - -/* ---------- - * Wait Events - Activity - * - * Use this category when a process is waiting because it has no work to do, - * unless the "Client" or "Timeout" category describes the situation better. - * Typically, this should only be used for background processes. - * ---------- - */ -typedef enum -{ - WAIT_EVENT_ARCHIVER_MAIN = PG_WAIT_ACTIVITY, - WAIT_EVENT_AUTOVACUUM_MAIN, - WAIT_EVENT_BGWRITER_HIBERNATE, - WAIT_EVENT_BGWRITER_MAIN, - WAIT_EVENT_CHECKPOINTER_MAIN, - WAIT_EVENT_LOGICAL_APPLY_MAIN, - WAIT_EVENT_LOGICAL_LAUNCHER_MAIN, - WAIT_EVENT_PGSTAT_MAIN, - WAIT_EVENT_RECOVERY_WAL_ALL, - WAIT_EVENT_RECOVERY_WAL_STREAM, - WAIT_EVENT_SYSLOGGER_MAIN, - WAIT_EVENT_WAL_RECEIVER_MAIN, - WAIT_EVENT_WAL_SENDER_MAIN, - WAIT_EVENT_WAL_WRITER_MAIN -} WaitEventActivity; - -/* ---------- - * Wait Events - Client - * - * Use this category when a process is waiting to send data to or receive data - * from the frontend process to which it is connected. This is never used for - * a background process, which has no client connection. - * ---------- - */ -typedef enum -{ - WAIT_EVENT_CLIENT_READ = PG_WAIT_CLIENT, - WAIT_EVENT_CLIENT_WRITE, - WAIT_EVENT_LIBPQWALRECEIVER_CONNECT, - WAIT_EVENT_LIBPQWALRECEIVER_RECEIVE, - WAIT_EVENT_SSL_OPEN_SERVER, - WAIT_EVENT_WAL_RECEIVER_WAIT_START, - WAIT_EVENT_WAL_SENDER_WAIT_WAL, - WAIT_EVENT_WAL_SENDER_WRITE_DATA -} WaitEventClient; - -/* ---------- - * Wait Events - IPC - * - * Use this category when a process cannot complete the work it is doing because - * it is waiting for a notification from another process. - * ---------- - */ -typedef enum -{ - WAIT_EVENT_BGWORKER_SHUTDOWN = PG_WAIT_IPC, - WAIT_EVENT_BGWORKER_STARTUP, - WAIT_EVENT_BTREE_PAGE, - WAIT_EVENT_CLOG_GROUP_UPDATE, - WAIT_EVENT_EXECUTE_GATHER, - WAIT_EVENT_HASH_BATCH_ALLOCATING, - WAIT_EVENT_HASH_BATCH_ELECTING, - WAIT_EVENT_HASH_BATCH_LOADING, - WAIT_EVENT_HASH_BUILD_ALLOCATING, - WAIT_EVENT_HASH_BUILD_ELECTING, - WAIT_EVENT_HASH_BUILD_HASHING_INNER, - WAIT_EVENT_HASH_BUILD_HASHING_OUTER, - WAIT_EVENT_HASH_GROW_BATCHES_ALLOCATING, - WAIT_EVENT_HASH_GROW_BATCHES_DECIDING, - WAIT_EVENT_HASH_GROW_BATCHES_ELECTING, - WAIT_EVENT_HASH_GROW_BATCHES_FINISHING, - WAIT_EVENT_HASH_GROW_BATCHES_REPARTITIONING, - WAIT_EVENT_HASH_GROW_BUCKETS_ALLOCATING, - WAIT_EVENT_HASH_GROW_BUCKETS_ELECTING, - WAIT_EVENT_HASH_GROW_BUCKETS_REINSERTING, - WAIT_EVENT_LOGICAL_SYNC_DATA, - WAIT_EVENT_LOGICAL_SYNC_STATE_CHANGE, - WAIT_EVENT_MQ_INTERNAL, - WAIT_EVENT_MQ_PUT_MESSAGE, - WAIT_EVENT_MQ_RECEIVE, - WAIT_EVENT_MQ_SEND, - WAIT_EVENT_PARALLEL_BITMAP_SCAN, - WAIT_EVENT_PARALLEL_CREATE_INDEX_SCAN, - WAIT_EVENT_PARALLEL_FINISH, - WAIT_EVENT_PROCARRAY_GROUP_UPDATE, - WAIT_EVENT_PROMOTE, - WAIT_EVENT_REPLICATION_ORIGIN_DROP, - WAIT_EVENT_REPLICATION_SLOT_DROP, - WAIT_EVENT_SAFE_SNAPSHOT, - WAIT_EVENT_SYNC_REP -} WaitEventIPC; - -/* ---------- - * Wait Events - Timeout - * - * Use this category when a process is waiting for a timeout to expire. - * ---------- - */ -typedef enum -{ - WAIT_EVENT_BASE_BACKUP_THROTTLE = PG_WAIT_TIMEOUT, - WAIT_EVENT_PG_SLEEP, - WAIT_EVENT_RECOVERY_APPLY_DELAY -} WaitEventTimeout; - -/* ---------- - * Wait Events - IO - * - * Use this category when a process is waiting for a IO. - * ---------- - */ -typedef enum -{ - WAIT_EVENT_BUFFILE_READ = PG_WAIT_IO, - WAIT_EVENT_BUFFILE_WRITE, - WAIT_EVENT_CONTROL_FILE_READ, - WAIT_EVENT_CONTROL_FILE_SYNC, - WAIT_EVENT_CONTROL_FILE_SYNC_UPDATE, - WAIT_EVENT_CONTROL_FILE_WRITE, - WAIT_EVENT_CONTROL_FILE_WRITE_UPDATE, - WAIT_EVENT_COPY_FILE_READ, - WAIT_EVENT_COPY_FILE_WRITE, - WAIT_EVENT_DATA_FILE_EXTEND, - WAIT_EVENT_DATA_FILE_FLUSH, - WAIT_EVENT_DATA_FILE_IMMEDIATE_SYNC, - WAIT_EVENT_DATA_FILE_PREFETCH, - WAIT_EVENT_DATA_FILE_READ, - WAIT_EVENT_DATA_FILE_SYNC, - WAIT_EVENT_DATA_FILE_TRUNCATE, - WAIT_EVENT_DATA_FILE_WRITE, - WAIT_EVENT_DSM_FILL_ZERO_WRITE, - WAIT_EVENT_LOCK_FILE_ADDTODATADIR_READ, - WAIT_EVENT_LOCK_FILE_ADDTODATADIR_SYNC, - WAIT_EVENT_LOCK_FILE_ADDTODATADIR_WRITE, - WAIT_EVENT_LOCK_FILE_CREATE_READ, - WAIT_EVENT_LOCK_FILE_CREATE_SYNC, - WAIT_EVENT_LOCK_FILE_CREATE_WRITE, - WAIT_EVENT_LOCK_FILE_RECHECKDATADIR_READ, - WAIT_EVENT_LOGICAL_REWRITE_CHECKPOINT_SYNC, - WAIT_EVENT_LOGICAL_REWRITE_MAPPING_SYNC, - WAIT_EVENT_LOGICAL_REWRITE_MAPPING_WRITE, - WAIT_EVENT_LOGICAL_REWRITE_SYNC, - WAIT_EVENT_LOGICAL_REWRITE_TRUNCATE, - WAIT_EVENT_LOGICAL_REWRITE_WRITE, - WAIT_EVENT_RELATION_MAP_READ, - WAIT_EVENT_RELATION_MAP_SYNC, - WAIT_EVENT_RELATION_MAP_WRITE, - WAIT_EVENT_REORDER_BUFFER_READ, - WAIT_EVENT_REORDER_BUFFER_WRITE, - WAIT_EVENT_REORDER_LOGICAL_MAPPING_READ, - WAIT_EVENT_REPLICATION_SLOT_READ, - WAIT_EVENT_REPLICATION_SLOT_RESTORE_SYNC, - WAIT_EVENT_REPLICATION_SLOT_SYNC, - WAIT_EVENT_REPLICATION_SLOT_WRITE, - WAIT_EVENT_SLRU_FLUSH_SYNC, - WAIT_EVENT_SLRU_READ, - WAIT_EVENT_SLRU_SYNC, - WAIT_EVENT_SLRU_WRITE, - WAIT_EVENT_SNAPBUILD_READ, - WAIT_EVENT_SNAPBUILD_SYNC, - WAIT_EVENT_SNAPBUILD_WRITE, - WAIT_EVENT_TIMELINE_HISTORY_FILE_SYNC, - WAIT_EVENT_TIMELINE_HISTORY_FILE_WRITE, - WAIT_EVENT_TIMELINE_HISTORY_READ, - WAIT_EVENT_TIMELINE_HISTORY_SYNC, - WAIT_EVENT_TIMELINE_HISTORY_WRITE, - WAIT_EVENT_TWOPHASE_FILE_READ, - WAIT_EVENT_TWOPHASE_FILE_SYNC, - WAIT_EVENT_TWOPHASE_FILE_WRITE, - WAIT_EVENT_WALSENDER_TIMELINE_HISTORY_READ, - WAIT_EVENT_WAL_BOOTSTRAP_SYNC, - WAIT_EVENT_WAL_BOOTSTRAP_WRITE, - WAIT_EVENT_WAL_COPY_READ, - WAIT_EVENT_WAL_COPY_SYNC, - WAIT_EVENT_WAL_COPY_WRITE, - WAIT_EVENT_WAL_INIT_SYNC, - WAIT_EVENT_WAL_INIT_WRITE, - WAIT_EVENT_WAL_READ, - WAIT_EVENT_WAL_SYNC, - WAIT_EVENT_WAL_SYNC_METHOD_ASSIGN, - WAIT_EVENT_WAL_WRITE -} WaitEventIO; - -/* ---------- - * Command type for progress reporting purposes - * ---------- - */ -typedef enum ProgressCommandType -{ - PROGRESS_COMMAND_INVALID, - PROGRESS_COMMAND_VACUUM -} ProgressCommandType; - -#define PGSTAT_NUM_PROGRESS_PARAM 10 - -/* ---------- - * Shared-memory data structures - * ---------- - */ - - -/* - * PgBackendSSLStatus - * - * For each backend, we keep the SSL status in a separate struct, that - * is only filled in if SSL is enabled. - */ -typedef struct PgBackendSSLStatus -{ - /* Information about SSL connection */ - int ssl_bits; - bool ssl_compression; - char ssl_version[NAMEDATALEN]; /* MUST be null-terminated */ - char ssl_cipher[NAMEDATALEN]; /* MUST be null-terminated */ - char ssl_clientdn[NAMEDATALEN]; /* MUST be null-terminated */ -} PgBackendSSLStatus; - - -/* ---------- - * PgBackendStatus - * - * Each live backend maintains a PgBackendStatus struct in shared memory - * showing its current activity. (The structs are allocated according to - * BackendId, but that is not critical.) Note that the collector process - * has no involvement in, or even access to, these structs. - * - * Each auxiliary process also maintains a PgBackendStatus struct in shared - * memory. - * ---------- - */ -typedef struct PgBackendStatus -{ - /* - * To avoid locking overhead, we use the following protocol: a backend - * increments st_changecount before modifying its entry, and again after - * finishing a modification. A would-be reader should note the value of - * st_changecount, copy the entry into private memory, then check - * st_changecount again. If the value hasn't changed, and if it's even, - * the copy is valid; otherwise start over. This makes updates cheap - * while reads are potentially expensive, but that's the tradeoff we want. - * - * The above protocol needs the memory barriers to ensure that the - * apparent order of execution is as it desires. Otherwise, for example, - * the CPU might rearrange the code so that st_changecount is incremented - * twice before the modification on a machine with weak memory ordering. - * This surprising result can lead to bugs. - */ - int st_changecount; - - /* The entry is valid iff st_procpid > 0, unused if st_procpid == 0 */ - int st_procpid; - - /* Type of backends */ - BackendType st_backendType; - - /* Times when current backend, transaction, and activity started */ - TimestampTz st_proc_start_timestamp; - TimestampTz st_xact_start_timestamp; - TimestampTz st_activity_start_timestamp; - TimestampTz st_state_start_timestamp; - - /* Database OID, owning user's OID, connection client address */ - Oid st_databaseid; - Oid st_userid; - SockAddr st_clientaddr; - char *st_clienthostname; /* MUST be null-terminated */ - - /* Information about SSL connection */ - bool st_ssl; - PgBackendSSLStatus *st_sslstatus; - - /* current state */ - BackendState st_state; - - /* application name; MUST be null-terminated */ - char *st_appname; - - /* - * Current command string; MUST be null-terminated. Note that this string - * possibly is truncated in the middle of a multi-byte character. As - * activity strings are stored more frequently than read, that allows to - * move the cost of correct truncation to the display side. Use - * pgstat_clip_activity() to truncate correctly. - */ - char *st_activity_raw; - - /* - * Command progress reporting. Any command which wishes can advertise - * that it is running by setting st_progress_command, - * st_progress_command_target, and st_progress_param[]. - * st_progress_command_target should be the OID of the relation which the - * command targets (we assume there's just one, as this is meant for - * utility commands), but the meaning of each element in the - * st_progress_param array is command-specific. - */ - ProgressCommandType st_progress_command; - Oid st_progress_command_target; - int64 st_progress_param[PGSTAT_NUM_PROGRESS_PARAM]; -} PgBackendStatus; - -/* - * Macros to load and store st_changecount with the memory barriers. - * - * pgstat_increment_changecount_before() and - * pgstat_increment_changecount_after() need to be called before and after - * PgBackendStatus entries are modified, respectively. This makes sure that - * st_changecount is incremented around the modification. - * - * Also pgstat_save_changecount_before() and pgstat_save_changecount_after() - * need to be called before and after PgBackendStatus entries are copied into - * private memory, respectively. - */ -#define pgstat_increment_changecount_before(beentry) \ - do { \ - beentry->st_changecount++; \ - pg_write_barrier(); \ - } while (0) - -#define pgstat_increment_changecount_after(beentry) \ - do { \ - pg_write_barrier(); \ - beentry->st_changecount++; \ - Assert((beentry->st_changecount & 1) == 0); \ - } while (0) - -#define pgstat_save_changecount_before(beentry, save_changecount) \ - do { \ - save_changecount = beentry->st_changecount; \ - pg_read_barrier(); \ - } while (0) - -#define pgstat_save_changecount_after(beentry, save_changecount) \ - do { \ - pg_read_barrier(); \ - save_changecount = beentry->st_changecount; \ - } while (0) - -/* ---------- - * LocalPgBackendStatus - * - * When we build the backend status array, we use LocalPgBackendStatus to be - * able to add new values to the struct when needed without adding new fields - * to the shared memory. It contains the backend status as a first member. - * ---------- - */ -typedef struct LocalPgBackendStatus -{ - /* - * Local version of the backend status entry. - */ - PgBackendStatus backendStatus; - - /* - * The xid of the current transaction if available, InvalidTransactionId - * if not. - */ - TransactionId backend_xid; - - /* - * The xmin of the current session if available, InvalidTransactionId if - * not. - */ - TransactionId backend_xmin; -} LocalPgBackendStatus; - /* * Working state needed to accumulate per-function-call timing statistics. */ @@ -778,10 +358,8 @@ typedef struct PgStat_FunctionCallUsage * GUC parameters * ---------- */ -extern bool pgstat_track_activities; extern bool pgstat_track_counts; extern int pgstat_track_functions; -extern PGDLLIMPORT int pgstat_track_activity_query_size; extern char *pgstat_stat_directory; extern char *pgstat_stat_tmpname; extern char *pgstat_stat_filename; @@ -828,26 +406,9 @@ extern void pgstat_report_deadlock(void); extern void pgstat_clear_snapshot(void); extern void pgstat_initialize(void); +extern void pgstat_bearray_initialize(void); extern void pgstat_bestart(void); -extern void pgstat_report_activity(BackendState state, const char *cmd_str); -extern void pgstat_report_tempfile(size_t filesize); -extern void pgstat_report_appname(const char *appname); -extern void pgstat_report_xact_timestamp(TimestampTz tstamp); -extern const char *pgstat_get_wait_event(uint32 wait_event_info); -extern const char *pgstat_get_wait_event_type(uint32 wait_event_info); -extern const char *pgstat_get_backend_current_activity(int pid, bool checkUser); -extern const char *pgstat_get_crashed_backend_activity(int pid, char *buffer, - int buflen); -extern const char *pgstat_get_backend_desc(BackendType backendType); - -extern void pgstat_progress_start_command(ProgressCommandType cmdtype, - Oid relid); -extern void pgstat_progress_update_param(int index, int64 val); -extern void pgstat_progress_update_multi_param(int nparam, const int *index, - const int64 *val); -extern void pgstat_progress_end_command(void); - extern PgStat_TableStatus *find_tabstat_entry(Oid rel_id); extern PgStat_BackendFunctionEntry *find_funcstat_entry(Oid func_id); @@ -858,60 +419,6 @@ extern PgStat_StatDBEntry *backend_get_db_entry(Oid dbid, bool oneshot); extern HTAB *backend_snapshot_all_db_entries(void); extern PgStat_StatTabEntry *backend_get_tab_entry(PgStat_StatDBEntry *dbent, Oid relid, bool oneshot); -/* ---------- - * pgstat_report_wait_start() - - * - * Called from places where server process needs to wait. This is called - * to report wait event information. The wait information is stored - * as 4-bytes where first byte represents the wait event class (type of - * wait, for different types of wait, refer WaitClass) and the next - * 3-bytes represent the actual wait event. Currently 2-bytes are used - * for wait event which is sufficient for current usage, 1-byte is - * reserved for future usage. - * - * NB: this *must* be able to survive being called before MyProc has been - * initialized. - * ---------- - */ -static inline void -pgstat_report_wait_start(uint32 wait_event_info) -{ - volatile PGPROC *proc = MyProc; - - if (!pgstat_track_activities || !proc) - return; - - /* - * Since this is a four-byte field which is always read and written as - * four-bytes, updates are atomic. - */ - proc->wait_event_info = wait_event_info; -} - -/* ---------- - * pgstat_report_wait_end() - - * - * Called to report end of a wait. - * - * NB: this *must* be able to survive being called before MyProc has been - * initialized. - * ---------- - */ -static inline void -pgstat_report_wait_end(void) -{ - volatile PGPROC *proc = MyProc; - - if (!pgstat_track_activities || !proc) - return; - - /* - * Since this is a four-byte field which is always read and written as - * four-bytes, updates are atomic. - */ - proc->wait_event_info = 0; -} - /* nontransactional event counts are simple enough to inline */ #define pgstat_count_heap_scan(rel) \ @@ -979,6 +486,8 @@ extern void pgstat_twophase_postabort(TransactionId xid, uint16 info, extern void pgstat_update_archiver(const char *xlog, bool failed); extern void pgstat_update_bgwriter(void); +extern void pgstat_report_tempfile(size_t filesize); + /* ---------- * Support functions for the SQL-callable functions to * generate the pgstat* views. @@ -986,10 +495,7 @@ extern void pgstat_update_bgwriter(void); */ extern PgStat_StatDBEntry *pgstat_fetch_stat_dbentry(Oid relid, bool oneshot); extern PgStat_StatTabEntry *pgstat_fetch_stat_tabentry(Oid relid); -extern PgBackendStatus *pgstat_fetch_stat_beentry(int beid); -extern LocalPgBackendStatus *pgstat_fetch_stat_local_beentry(int beid); extern PgStat_StatFuncEntry *pgstat_fetch_stat_funcentry(Oid funcid); -extern int pgstat_fetch_stat_numbackends(void); extern PgStat_ArchiverStats *pgstat_fetch_stat_archiver(void); extern PgStat_GlobalStats *pgstat_fetch_global(void); -- 2.16.3 ----Next_Part(Thu_Nov_08_20_46_48_2018_519)----