1/* ----------
2 * pgstat.h
3 *
4 * Definitions for the PostgreSQL statistics collector daemon.
5 *
6 * Copyright (c) 2001-2019, PostgreSQL Global Development Group
7 *
8 * src/include/pgstat.h
9 * ----------
10 */
11#ifndef PGSTAT_H
12#define PGSTAT_H
13
14#include "datatype/timestamp.h"
15#include "fmgr.h"
16#include "libpq/pqcomm.h"
17#include "port/atomics.h"
18#include "portability/instr_time.h"
19#include "postmaster/pgarch.h"
20#include "storage/proc.h"
21#include "utils/hsearch.h"
22#include "utils/relcache.h"
23
24
25/* ----------
26 * Paths for the statistics files (relative to installation's $PGDATA).
27 * ----------
28 */
29#define PGSTAT_STAT_PERMANENT_DIRECTORY "pg_stat"
30#define PGSTAT_STAT_PERMANENT_FILENAME "pg_stat/global.stat"
31#define PGSTAT_STAT_PERMANENT_TMPFILE "pg_stat/global.tmp"
32
33/* Default directory to store temporary statistics data in */
34#define PG_STAT_TMP_DIR "pg_stat_tmp"
35
36/* Values for track_functions GUC variable --- order is significant! */
37typedef enum TrackFunctionsLevel
38{
39 TRACK_FUNC_OFF,
40 TRACK_FUNC_PL,
41 TRACK_FUNC_ALL
42} TrackFunctionsLevel;
43
44/* ----------
45 * The types of backend -> collector messages
46 * ----------
47 */
48typedef enum StatMsgType
49{
50 PGSTAT_MTYPE_DUMMY,
51 PGSTAT_MTYPE_INQUIRY,
52 PGSTAT_MTYPE_TABSTAT,
53 PGSTAT_MTYPE_TABPURGE,
54 PGSTAT_MTYPE_DROPDB,
55 PGSTAT_MTYPE_RESETCOUNTER,
56 PGSTAT_MTYPE_RESETSHAREDCOUNTER,
57 PGSTAT_MTYPE_RESETSINGLECOUNTER,
58 PGSTAT_MTYPE_AUTOVAC_START,
59 PGSTAT_MTYPE_VACUUM,
60 PGSTAT_MTYPE_ANALYZE,
61 PGSTAT_MTYPE_ARCHIVER,
62 PGSTAT_MTYPE_BGWRITER,
63 PGSTAT_MTYPE_FUNCSTAT,
64 PGSTAT_MTYPE_FUNCPURGE,
65 PGSTAT_MTYPE_RECOVERYCONFLICT,
66 PGSTAT_MTYPE_TEMPFILE,
67 PGSTAT_MTYPE_DEADLOCK,
68 PGSTAT_MTYPE_CHECKSUMFAILURE
69} StatMsgType;
70
71/* ----------
72 * The data type used for counters.
73 * ----------
74 */
75typedef int64 PgStat_Counter;
76
77/* ----------
78 * PgStat_TableCounts The actual per-table counts kept by a backend
79 *
80 * This struct should contain only actual event counters, because we memcmp
81 * it against zeroes to detect whether there are any counts to transmit.
82 * It is a component of PgStat_TableStatus (within-backend state) and
83 * PgStat_TableEntry (the transmitted message format).
84 *
85 * Note: for a table, tuples_returned is the number of tuples successfully
86 * fetched by heap_getnext, while tuples_fetched is the number of tuples
87 * successfully fetched by heap_fetch under the control of bitmap indexscans.
88 * For an index, tuples_returned is the number of index entries returned by
89 * the index AM, while tuples_fetched is the number of tuples successfully
90 * fetched by heap_fetch under the control of simple indexscans for this index.
91 *
92 * tuples_inserted/updated/deleted/hot_updated count attempted actions,
93 * regardless of whether the transaction committed. delta_live_tuples,
94 * delta_dead_tuples, and changed_tuples are set depending on commit or abort.
95 * Note that delta_live_tuples and delta_dead_tuples can be negative!
96 * ----------
97 */
98typedef struct PgStat_TableCounts
99{
100 PgStat_Counter t_numscans;
101
102 PgStat_Counter t_tuples_returned;
103 PgStat_Counter t_tuples_fetched;
104
105 PgStat_Counter t_tuples_inserted;
106 PgStat_Counter t_tuples_updated;
107 PgStat_Counter t_tuples_deleted;
108 PgStat_Counter t_tuples_hot_updated;
109 bool t_truncated;
110
111 PgStat_Counter t_delta_live_tuples;
112 PgStat_Counter t_delta_dead_tuples;
113 PgStat_Counter t_changed_tuples;
114
115 PgStat_Counter t_blocks_fetched;
116 PgStat_Counter t_blocks_hit;
117} PgStat_TableCounts;
118
119/* Possible targets for resetting cluster-wide shared values */
120typedef enum PgStat_Shared_Reset_Target
121{
122 RESET_ARCHIVER,
123 RESET_BGWRITER
124} PgStat_Shared_Reset_Target;
125
126/* Possible object types for resetting single counters */
127typedef enum PgStat_Single_Reset_Type
128{
129 RESET_TABLE,
130 RESET_FUNCTION
131} PgStat_Single_Reset_Type;
132
133/* ------------------------------------------------------------
134 * Structures kept in backend local memory while accumulating counts
135 * ------------------------------------------------------------
136 */
137
138
139/* ----------
140 * PgStat_TableStatus Per-table status within a backend
141 *
142 * Many of the event counters are nontransactional, ie, we count events
143 * in committed and aborted transactions alike. For these, we just count
144 * directly in the PgStat_TableStatus. However, delta_live_tuples,
145 * delta_dead_tuples, and changed_tuples must be derived from event counts
146 * with awareness of whether the transaction or subtransaction committed or
147 * aborted. Hence, we also keep a stack of per-(sub)transaction status
148 * records for every table modified in the current transaction. At commit
149 * or abort, we propagate tuples_inserted/updated/deleted up to the
150 * parent subtransaction level, or out to the parent PgStat_TableStatus,
151 * as appropriate.
152 * ----------
153 */
154typedef struct PgStat_TableStatus
155{
156 Oid t_id; /* table's OID */
157 bool t_shared; /* is it a shared catalog? */
158 struct PgStat_TableXactStatus *trans; /* lowest subxact's counts */
159 PgStat_TableCounts t_counts; /* event counts to be sent */
160} PgStat_TableStatus;
161
162/* ----------
163 * PgStat_TableXactStatus Per-table, per-subtransaction status
164 * ----------
165 */
166typedef struct PgStat_TableXactStatus
167{
168 PgStat_Counter tuples_inserted; /* tuples inserted in (sub)xact */
169 PgStat_Counter tuples_updated; /* tuples updated in (sub)xact */
170 PgStat_Counter tuples_deleted; /* tuples deleted in (sub)xact */
171 bool truncated; /* relation truncated in this (sub)xact */
172 PgStat_Counter inserted_pre_trunc; /* tuples inserted prior to truncate */
173 PgStat_Counter updated_pre_trunc; /* tuples updated prior to truncate */
174 PgStat_Counter deleted_pre_trunc; /* tuples deleted prior to truncate */
175 int nest_level; /* subtransaction nest level */
176 /* links to other structs for same relation: */
177 struct PgStat_TableXactStatus *upper; /* next higher subxact if any */
178 PgStat_TableStatus *parent; /* per-table status */
179 /* structs of same subxact level are linked here: */
180 struct PgStat_TableXactStatus *next; /* next of same subxact */
181} PgStat_TableXactStatus;
182
183
184/* ------------------------------------------------------------
185 * Message formats follow
186 * ------------------------------------------------------------
187 */
188
189
190/* ----------
191 * PgStat_MsgHdr The common message header
192 * ----------
193 */
194typedef struct PgStat_MsgHdr
195{
196 StatMsgType m_type;
197 int m_size;
198} PgStat_MsgHdr;
199
200/* ----------
201 * Space available in a message. This will keep the UDP packets below 1K,
202 * which should fit unfragmented into the MTU of the loopback interface.
203 * (Larger values of PGSTAT_MAX_MSG_SIZE would work for that on most
204 * platforms, but we're being conservative here.)
205 * ----------
206 */
207#define PGSTAT_MAX_MSG_SIZE 1000
208#define PGSTAT_MSG_PAYLOAD (PGSTAT_MAX_MSG_SIZE - sizeof(PgStat_MsgHdr))
209
210
211/* ----------
212 * PgStat_MsgDummy A dummy message, ignored by the collector
213 * ----------
214 */
215typedef struct PgStat_MsgDummy
216{
217 PgStat_MsgHdr m_hdr;
218} PgStat_MsgDummy;
219
220
221/* ----------
222 * PgStat_MsgInquiry Sent by a backend to ask the collector
223 * to write the stats file(s).
224 *
225 * Ordinarily, an inquiry message prompts writing of the global stats file,
226 * the stats file for shared catalogs, and the stats file for the specified
227 * database. If databaseid is InvalidOid, only the first two are written.
228 *
229 * New file(s) will be written only if the existing file has a timestamp
230 * older than the specified cutoff_time; this prevents duplicated effort
231 * when multiple requests arrive at nearly the same time, assuming that
232 * backends send requests with cutoff_times a little bit in the past.
233 *
234 * clock_time should be the requestor's current local time; the collector
235 * uses this to check for the system clock going backward, but it has no
236 * effect unless that occurs. We assume clock_time >= cutoff_time, though.
237 * ----------
238 */
239
240typedef struct PgStat_MsgInquiry
241{
242 PgStat_MsgHdr m_hdr;
243 TimestampTz clock_time; /* observed local clock time */
244 TimestampTz cutoff_time; /* minimum acceptable file timestamp */
245 Oid databaseid; /* requested DB (InvalidOid => shared only) */
246} PgStat_MsgInquiry;
247
248
249/* ----------
250 * PgStat_TableEntry Per-table info in a MsgTabstat
251 * ----------
252 */
253typedef struct PgStat_TableEntry
254{
255 Oid t_id;
256 PgStat_TableCounts t_counts;
257} PgStat_TableEntry;
258
259/* ----------
260 * PgStat_MsgTabstat Sent by the backend to report table
261 * and buffer access statistics.
262 * ----------
263 */
264#define PGSTAT_NUM_TABENTRIES \
265 ((PGSTAT_MSG_PAYLOAD - sizeof(Oid) - 3 * sizeof(int) - 2 * sizeof(PgStat_Counter)) \
266 / sizeof(PgStat_TableEntry))
267
268typedef struct PgStat_MsgTabstat
269{
270 PgStat_MsgHdr m_hdr;
271 Oid m_databaseid;
272 int m_nentries;
273 int m_xact_commit;
274 int m_xact_rollback;
275 PgStat_Counter m_block_read_time; /* times in microseconds */
276 PgStat_Counter m_block_write_time;
277 PgStat_TableEntry m_entry[PGSTAT_NUM_TABENTRIES];
278} PgStat_MsgTabstat;
279
280
281/* ----------
282 * PgStat_MsgTabpurge Sent by the backend to tell the collector
283 * about dead tables.
284 * ----------
285 */
286#define PGSTAT_NUM_TABPURGE \
287 ((PGSTAT_MSG_PAYLOAD - sizeof(Oid) - sizeof(int)) \
288 / sizeof(Oid))
289
290typedef struct PgStat_MsgTabpurge
291{
292 PgStat_MsgHdr m_hdr;
293 Oid m_databaseid;
294 int m_nentries;
295 Oid m_tableid[PGSTAT_NUM_TABPURGE];
296} PgStat_MsgTabpurge;
297
298
299/* ----------
300 * PgStat_MsgDropdb Sent by the backend to tell the collector
301 * about a dropped database
302 * ----------
303 */
304typedef struct PgStat_MsgDropdb
305{
306 PgStat_MsgHdr m_hdr;
307 Oid m_databaseid;
308} PgStat_MsgDropdb;
309
310
311/* ----------
312 * PgStat_MsgResetcounter Sent by the backend to tell the collector
313 * to reset counters
314 * ----------
315 */
316typedef struct PgStat_MsgResetcounter
317{
318 PgStat_MsgHdr m_hdr;
319 Oid m_databaseid;
320} PgStat_MsgResetcounter;
321
322/* ----------
323 * PgStat_MsgResetsharedcounter Sent by the backend to tell the collector
324 * to reset a shared counter
325 * ----------
326 */
327typedef struct PgStat_MsgResetsharedcounter
328{
329 PgStat_MsgHdr m_hdr;
330 PgStat_Shared_Reset_Target m_resettarget;
331} PgStat_MsgResetsharedcounter;
332
333/* ----------
334 * PgStat_MsgResetsinglecounter Sent by the backend to tell the collector
335 * to reset a single counter
336 * ----------
337 */
338typedef struct PgStat_MsgResetsinglecounter
339{
340 PgStat_MsgHdr m_hdr;
341 Oid m_databaseid;
342 PgStat_Single_Reset_Type m_resettype;
343 Oid m_objectid;
344} PgStat_MsgResetsinglecounter;
345
346/* ----------
347 * PgStat_MsgAutovacStart Sent by the autovacuum daemon to signal
348 * that a database is going to be processed
349 * ----------
350 */
351typedef struct PgStat_MsgAutovacStart
352{
353 PgStat_MsgHdr m_hdr;
354 Oid m_databaseid;
355 TimestampTz m_start_time;
356} PgStat_MsgAutovacStart;
357
358
359/* ----------
360 * PgStat_MsgVacuum Sent by the backend or autovacuum daemon
361 * after VACUUM
362 * ----------
363 */
364typedef struct PgStat_MsgVacuum
365{
366 PgStat_MsgHdr m_hdr;
367 Oid m_databaseid;
368 Oid m_tableoid;
369 bool m_autovacuum;
370 TimestampTz m_vacuumtime;
371 PgStat_Counter m_live_tuples;
372 PgStat_Counter m_dead_tuples;
373} PgStat_MsgVacuum;
374
375
376/* ----------
377 * PgStat_MsgAnalyze Sent by the backend or autovacuum daemon
378 * after ANALYZE
379 * ----------
380 */
381typedef struct PgStat_MsgAnalyze
382{
383 PgStat_MsgHdr m_hdr;
384 Oid m_databaseid;
385 Oid m_tableoid;
386 bool m_autovacuum;
387 bool m_resetcounter;
388 TimestampTz m_analyzetime;
389 PgStat_Counter m_live_tuples;
390 PgStat_Counter m_dead_tuples;
391} PgStat_MsgAnalyze;
392
393
394/* ----------
395 * PgStat_MsgArchiver Sent by the archiver to update statistics.
396 * ----------
397 */
398typedef struct PgStat_MsgArchiver
399{
400 PgStat_MsgHdr m_hdr;
401 bool m_failed; /* Failed attempt */
402 char m_xlog[MAX_XFN_CHARS + 1];
403 TimestampTz m_timestamp;
404} PgStat_MsgArchiver;
405
406/* ----------
407 * PgStat_MsgBgWriter Sent by the bgwriter to update statistics.
408 * ----------
409 */
410typedef struct PgStat_MsgBgWriter
411{
412 PgStat_MsgHdr m_hdr;
413
414 PgStat_Counter m_timed_checkpoints;
415 PgStat_Counter m_requested_checkpoints;
416 PgStat_Counter m_buf_written_checkpoints;
417 PgStat_Counter m_buf_written_clean;
418 PgStat_Counter m_maxwritten_clean;
419 PgStat_Counter m_buf_written_backend;
420 PgStat_Counter m_buf_fsync_backend;
421 PgStat_Counter m_buf_alloc;
422 PgStat_Counter m_checkpoint_write_time; /* times in milliseconds */
423 PgStat_Counter m_checkpoint_sync_time;
424} PgStat_MsgBgWriter;
425
426/* ----------
427 * PgStat_MsgRecoveryConflict Sent by the backend upon recovery conflict
428 * ----------
429 */
430typedef struct PgStat_MsgRecoveryConflict
431{
432 PgStat_MsgHdr m_hdr;
433
434 Oid m_databaseid;
435 int m_reason;
436} PgStat_MsgRecoveryConflict;
437
438/* ----------
439 * PgStat_MsgTempFile Sent by the backend upon creating a temp file
440 * ----------
441 */
442typedef struct PgStat_MsgTempFile
443{
444 PgStat_MsgHdr m_hdr;
445
446 Oid m_databaseid;
447 size_t m_filesize;
448} PgStat_MsgTempFile;
449
450/* ----------
451 * PgStat_FunctionCounts The actual per-function counts kept by a backend
452 *
453 * This struct should contain only actual event counters, because we memcmp
454 * it against zeroes to detect whether there are any counts to transmit.
455 *
456 * Note that the time counters are in instr_time format here. We convert to
457 * microseconds in PgStat_Counter format when transmitting to the collector.
458 * ----------
459 */
460typedef struct PgStat_FunctionCounts
461{
462 PgStat_Counter f_numcalls;
463 instr_time f_total_time;
464 instr_time f_self_time;
465} PgStat_FunctionCounts;
466
467/* ----------
468 * PgStat_BackendFunctionEntry Entry in backend's per-function hash table
469 * ----------
470 */
471typedef struct PgStat_BackendFunctionEntry
472{
473 Oid f_id;
474 PgStat_FunctionCounts f_counts;
475} PgStat_BackendFunctionEntry;
476
477/* ----------
478 * PgStat_FunctionEntry Per-function info in a MsgFuncstat
479 * ----------
480 */
481typedef struct PgStat_FunctionEntry
482{
483 Oid f_id;
484 PgStat_Counter f_numcalls;
485 PgStat_Counter f_total_time; /* times in microseconds */
486 PgStat_Counter f_self_time;
487} PgStat_FunctionEntry;
488
489/* ----------
490 * PgStat_MsgFuncstat Sent by the backend to report function
491 * usage statistics.
492 * ----------
493 */
494#define PGSTAT_NUM_FUNCENTRIES \
495 ((PGSTAT_MSG_PAYLOAD - sizeof(Oid) - sizeof(int)) \
496 / sizeof(PgStat_FunctionEntry))
497
498typedef struct PgStat_MsgFuncstat
499{
500 PgStat_MsgHdr m_hdr;
501 Oid m_databaseid;
502 int m_nentries;
503 PgStat_FunctionEntry m_entry[PGSTAT_NUM_FUNCENTRIES];
504} PgStat_MsgFuncstat;
505
506/* ----------
507 * PgStat_MsgFuncpurge Sent by the backend to tell the collector
508 * about dead functions.
509 * ----------
510 */
511#define PGSTAT_NUM_FUNCPURGE \
512 ((PGSTAT_MSG_PAYLOAD - sizeof(Oid) - sizeof(int)) \
513 / sizeof(Oid))
514
515typedef struct PgStat_MsgFuncpurge
516{
517 PgStat_MsgHdr m_hdr;
518 Oid m_databaseid;
519 int m_nentries;
520 Oid m_functionid[PGSTAT_NUM_FUNCPURGE];
521} PgStat_MsgFuncpurge;
522
523/* ----------
524 * PgStat_MsgDeadlock Sent by the backend to tell the collector
525 * about a deadlock that occurred.
526 * ----------
527 */
528typedef struct PgStat_MsgDeadlock
529{
530 PgStat_MsgHdr m_hdr;
531 Oid m_databaseid;
532} PgStat_MsgDeadlock;
533
534/* ----------
535 * PgStat_MsgChecksumFailure Sent by the backend to tell the collector
536 * about checksum failures noticed.
537 * ----------
538 */
539typedef struct PgStat_MsgChecksumFailure
540{
541 PgStat_MsgHdr m_hdr;
542 Oid m_databaseid;
543 int m_failurecount;
544 TimestampTz m_failure_time;
545} PgStat_MsgChecksumFailure;
546
547
548/* ----------
549 * PgStat_Msg Union over all possible messages.
550 * ----------
551 */
552typedef union PgStat_Msg
553{
554 PgStat_MsgHdr msg_hdr;
555 PgStat_MsgDummy msg_dummy;
556 PgStat_MsgInquiry msg_inquiry;
557 PgStat_MsgTabstat msg_tabstat;
558 PgStat_MsgTabpurge msg_tabpurge;
559 PgStat_MsgDropdb msg_dropdb;
560 PgStat_MsgResetcounter msg_resetcounter;
561 PgStat_MsgResetsharedcounter msg_resetsharedcounter;
562 PgStat_MsgResetsinglecounter msg_resetsinglecounter;
563 PgStat_MsgAutovacStart msg_autovacuum_start;
564 PgStat_MsgVacuum msg_vacuum;
565 PgStat_MsgAnalyze msg_analyze;
566 PgStat_MsgArchiver msg_archiver;
567 PgStat_MsgBgWriter msg_bgwriter;
568 PgStat_MsgFuncstat msg_funcstat;
569 PgStat_MsgFuncpurge msg_funcpurge;
570 PgStat_MsgRecoveryConflict msg_recoveryconflict;
571 PgStat_MsgDeadlock msg_deadlock;
572 PgStat_MsgTempFile msg_tempfile;
573 PgStat_MsgChecksumFailure msg_checksumfailure;
574} PgStat_Msg;
575
576
577/* ------------------------------------------------------------
578 * Statistic collector data structures follow
579 *
580 * PGSTAT_FILE_FORMAT_ID should be changed whenever any of these
581 * data structures change.
582 * ------------------------------------------------------------
583 */
584
585#define PGSTAT_FILE_FORMAT_ID 0x01A5BC9D
586
587/* ----------
588 * PgStat_StatDBEntry The collector's data per database
589 * ----------
590 */
591typedef struct PgStat_StatDBEntry
592{
593 Oid databaseid;
594 PgStat_Counter n_xact_commit;
595 PgStat_Counter n_xact_rollback;
596 PgStat_Counter n_blocks_fetched;
597 PgStat_Counter n_blocks_hit;
598 PgStat_Counter n_tuples_returned;
599 PgStat_Counter n_tuples_fetched;
600 PgStat_Counter n_tuples_inserted;
601 PgStat_Counter n_tuples_updated;
602 PgStat_Counter n_tuples_deleted;
603 TimestampTz last_autovac_time;
604 PgStat_Counter n_conflict_tablespace;
605 PgStat_Counter n_conflict_lock;
606 PgStat_Counter n_conflict_snapshot;
607 PgStat_Counter n_conflict_bufferpin;
608 PgStat_Counter n_conflict_startup_deadlock;
609 PgStat_Counter n_temp_files;
610 PgStat_Counter n_temp_bytes;
611 PgStat_Counter n_deadlocks;
612 PgStat_Counter n_checksum_failures;
613 TimestampTz last_checksum_failure;
614 PgStat_Counter n_block_read_time; /* times in microseconds */
615 PgStat_Counter n_block_write_time;
616
617 TimestampTz stat_reset_timestamp;
618 TimestampTz stats_timestamp; /* time of db stats file update */
619
620 /*
621 * tables and functions must be last in the struct, because we don't write
622 * the pointers out to the stats file.
623 */
624 HTAB *tables;
625 HTAB *functions;
626} PgStat_StatDBEntry;
627
628
629/* ----------
630 * PgStat_StatTabEntry The collector's data per table (or index)
631 * ----------
632 */
633typedef struct PgStat_StatTabEntry
634{
635 Oid tableid;
636
637 PgStat_Counter numscans;
638
639 PgStat_Counter tuples_returned;
640 PgStat_Counter tuples_fetched;
641
642 PgStat_Counter tuples_inserted;
643 PgStat_Counter tuples_updated;
644 PgStat_Counter tuples_deleted;
645 PgStat_Counter tuples_hot_updated;
646
647 PgStat_Counter n_live_tuples;
648 PgStat_Counter n_dead_tuples;
649 PgStat_Counter changes_since_analyze;
650
651 PgStat_Counter blocks_fetched;
652 PgStat_Counter blocks_hit;
653
654 TimestampTz vacuum_timestamp; /* user initiated vacuum */
655 PgStat_Counter vacuum_count;
656 TimestampTz autovac_vacuum_timestamp; /* autovacuum initiated */
657 PgStat_Counter autovac_vacuum_count;
658 TimestampTz analyze_timestamp; /* user initiated */
659 PgStat_Counter analyze_count;
660 TimestampTz autovac_analyze_timestamp; /* autovacuum initiated */
661 PgStat_Counter autovac_analyze_count;
662} PgStat_StatTabEntry;
663
664
665/* ----------
666 * PgStat_StatFuncEntry The collector's data per function
667 * ----------
668 */
669typedef struct PgStat_StatFuncEntry
670{
671 Oid functionid;
672
673 PgStat_Counter f_numcalls;
674
675 PgStat_Counter f_total_time; /* times in microseconds */
676 PgStat_Counter f_self_time;
677} PgStat_StatFuncEntry;
678
679
680/*
681 * Archiver statistics kept in the stats collector
682 */
683typedef struct PgStat_ArchiverStats
684{
685 PgStat_Counter archived_count; /* archival successes */
686 char last_archived_wal[MAX_XFN_CHARS + 1]; /* last WAL file
687 * archived */
688 TimestampTz last_archived_timestamp; /* last archival success time */
689 PgStat_Counter failed_count; /* failed archival attempts */
690 char last_failed_wal[MAX_XFN_CHARS + 1]; /* WAL file involved in
691 * last failure */
692 TimestampTz last_failed_timestamp; /* last archival failure time */
693 TimestampTz stat_reset_timestamp;
694} PgStat_ArchiverStats;
695
696/*
697 * Global statistics kept in the stats collector
698 */
699typedef struct PgStat_GlobalStats
700{
701 TimestampTz stats_timestamp; /* time of stats file update */
702 PgStat_Counter timed_checkpoints;
703 PgStat_Counter requested_checkpoints;
704 PgStat_Counter checkpoint_write_time; /* times in milliseconds */
705 PgStat_Counter checkpoint_sync_time;
706 PgStat_Counter buf_written_checkpoints;
707 PgStat_Counter buf_written_clean;
708 PgStat_Counter maxwritten_clean;
709 PgStat_Counter buf_written_backend;
710 PgStat_Counter buf_fsync_backend;
711 PgStat_Counter buf_alloc;
712 TimestampTz stat_reset_timestamp;
713} PgStat_GlobalStats;
714
715
716/* ----------
717 * Backend types
718 * ----------
719 */
720typedef enum BackendType
721{
722 B_AUTOVAC_LAUNCHER,
723 B_AUTOVAC_WORKER,
724 B_BACKEND,
725 B_BG_WORKER,
726 B_BG_WRITER,
727 B_CHECKPOINTER,
728 B_STARTUP,
729 B_WAL_RECEIVER,
730 B_WAL_SENDER,
731 B_WAL_WRITER
732} BackendType;
733
734
735/* ----------
736 * Backend states
737 * ----------
738 */
739typedef enum BackendState
740{
741 STATE_UNDEFINED,
742 STATE_IDLE,
743 STATE_RUNNING,
744 STATE_IDLEINTRANSACTION,
745 STATE_FASTPATH,
746 STATE_IDLEINTRANSACTION_ABORTED,
747 STATE_DISABLED
748} BackendState;
749
750
751/* ----------
752 * Wait Classes
753 * ----------
754 */
755#define PG_WAIT_LWLOCK 0x01000000U
756#define PG_WAIT_LOCK 0x03000000U
757#define PG_WAIT_BUFFER_PIN 0x04000000U
758#define PG_WAIT_ACTIVITY 0x05000000U
759#define PG_WAIT_CLIENT 0x06000000U
760#define PG_WAIT_EXTENSION 0x07000000U
761#define PG_WAIT_IPC 0x08000000U
762#define PG_WAIT_TIMEOUT 0x09000000U
763#define PG_WAIT_IO 0x0A000000U
764
765/* ----------
766 * Wait Events - Activity
767 *
768 * Use this category when a process is waiting because it has no work to do,
769 * unless the "Client" or "Timeout" category describes the situation better.
770 * Typically, this should only be used for background processes.
771 * ----------
772 */
773typedef enum
774{
775 WAIT_EVENT_ARCHIVER_MAIN = PG_WAIT_ACTIVITY,
776 WAIT_EVENT_AUTOVACUUM_MAIN,
777 WAIT_EVENT_BGWRITER_HIBERNATE,
778 WAIT_EVENT_BGWRITER_MAIN,
779 WAIT_EVENT_CHECKPOINTER_MAIN,
780 WAIT_EVENT_LOGICAL_APPLY_MAIN,
781 WAIT_EVENT_LOGICAL_LAUNCHER_MAIN,
782 WAIT_EVENT_PGSTAT_MAIN,
783 WAIT_EVENT_RECOVERY_WAL_ALL,
784 WAIT_EVENT_RECOVERY_WAL_STREAM,
785 WAIT_EVENT_SYSLOGGER_MAIN,
786 WAIT_EVENT_WAL_RECEIVER_MAIN,
787 WAIT_EVENT_WAL_SENDER_MAIN,
788 WAIT_EVENT_WAL_WRITER_MAIN
789} WaitEventActivity;
790
791/* ----------
792 * Wait Events - Client
793 *
794 * Use this category when a process is waiting to send data to or receive data
795 * from the frontend process to which it is connected. This is never used for
796 * a background process, which has no client connection.
797 * ----------
798 */
799typedef enum
800{
801 WAIT_EVENT_CLIENT_READ = PG_WAIT_CLIENT,
802 WAIT_EVENT_CLIENT_WRITE,
803 WAIT_EVENT_LIBPQWALRECEIVER_CONNECT,
804 WAIT_EVENT_LIBPQWALRECEIVER_RECEIVE,
805 WAIT_EVENT_SSL_OPEN_SERVER,
806 WAIT_EVENT_WAL_RECEIVER_WAIT_START,
807 WAIT_EVENT_WAL_SENDER_WAIT_WAL,
808 WAIT_EVENT_WAL_SENDER_WRITE_DATA,
809 WAIT_EVENT_GSS_OPEN_SERVER,
810} WaitEventClient;
811
812/* ----------
813 * Wait Events - IPC
814 *
815 * Use this category when a process cannot complete the work it is doing because
816 * it is waiting for a notification from another process.
817 * ----------
818 */
819typedef enum
820{
821 WAIT_EVENT_BGWORKER_SHUTDOWN = PG_WAIT_IPC,
822 WAIT_EVENT_BGWORKER_STARTUP,
823 WAIT_EVENT_BTREE_PAGE,
824 WAIT_EVENT_CLOG_GROUP_UPDATE,
825 WAIT_EVENT_CHECKPOINT_DONE,
826 WAIT_EVENT_CHECKPOINT_START,
827 WAIT_EVENT_EXECUTE_GATHER,
828 WAIT_EVENT_HASH_BATCH_ALLOCATING,
829 WAIT_EVENT_HASH_BATCH_ELECTING,
830 WAIT_EVENT_HASH_BATCH_LOADING,
831 WAIT_EVENT_HASH_BUILD_ALLOCATING,
832 WAIT_EVENT_HASH_BUILD_ELECTING,
833 WAIT_EVENT_HASH_BUILD_HASHING_INNER,
834 WAIT_EVENT_HASH_BUILD_HASHING_OUTER,
835 WAIT_EVENT_HASH_GROW_BATCHES_ALLOCATING,
836 WAIT_EVENT_HASH_GROW_BATCHES_DECIDING,
837 WAIT_EVENT_HASH_GROW_BATCHES_ELECTING,
838 WAIT_EVENT_HASH_GROW_BATCHES_FINISHING,
839 WAIT_EVENT_HASH_GROW_BATCHES_REPARTITIONING,
840 WAIT_EVENT_HASH_GROW_BUCKETS_ALLOCATING,
841 WAIT_EVENT_HASH_GROW_BUCKETS_ELECTING,
842 WAIT_EVENT_HASH_GROW_BUCKETS_REINSERTING,
843 WAIT_EVENT_LOGICAL_SYNC_DATA,
844 WAIT_EVENT_LOGICAL_SYNC_STATE_CHANGE,
845 WAIT_EVENT_MQ_INTERNAL,
846 WAIT_EVENT_MQ_PUT_MESSAGE,
847 WAIT_EVENT_MQ_RECEIVE,
848 WAIT_EVENT_MQ_SEND,
849 WAIT_EVENT_PARALLEL_BITMAP_SCAN,
850 WAIT_EVENT_PARALLEL_CREATE_INDEX_SCAN,
851 WAIT_EVENT_PARALLEL_FINISH,
852 WAIT_EVENT_PROCARRAY_GROUP_UPDATE,
853 WAIT_EVENT_PROMOTE,
854 WAIT_EVENT_REPLICATION_ORIGIN_DROP,
855 WAIT_EVENT_REPLICATION_SLOT_DROP,
856 WAIT_EVENT_SAFE_SNAPSHOT,
857 WAIT_EVENT_SYNC_REP
858} WaitEventIPC;
859
860/* ----------
861 * Wait Events - Timeout
862 *
863 * Use this category when a process is waiting for a timeout to expire.
864 * ----------
865 */
866typedef enum
867{
868 WAIT_EVENT_BASE_BACKUP_THROTTLE = PG_WAIT_TIMEOUT,
869 WAIT_EVENT_PG_SLEEP,
870 WAIT_EVENT_RECOVERY_APPLY_DELAY
871} WaitEventTimeout;
872
873/* ----------
874 * Wait Events - IO
875 *
876 * Use this category when a process is waiting for a IO.
877 * ----------
878 */
879typedef enum
880{
881 WAIT_EVENT_BUFFILE_READ = PG_WAIT_IO,
882 WAIT_EVENT_BUFFILE_WRITE,
883 WAIT_EVENT_CONTROL_FILE_READ,
884 WAIT_EVENT_CONTROL_FILE_SYNC,
885 WAIT_EVENT_CONTROL_FILE_SYNC_UPDATE,
886 WAIT_EVENT_CONTROL_FILE_WRITE,
887 WAIT_EVENT_CONTROL_FILE_WRITE_UPDATE,
888 WAIT_EVENT_COPY_FILE_READ,
889 WAIT_EVENT_COPY_FILE_WRITE,
890 WAIT_EVENT_DATA_FILE_EXTEND,
891 WAIT_EVENT_DATA_FILE_FLUSH,
892 WAIT_EVENT_DATA_FILE_IMMEDIATE_SYNC,
893 WAIT_EVENT_DATA_FILE_PREFETCH,
894 WAIT_EVENT_DATA_FILE_READ,
895 WAIT_EVENT_DATA_FILE_SYNC,
896 WAIT_EVENT_DATA_FILE_TRUNCATE,
897 WAIT_EVENT_DATA_FILE_WRITE,
898 WAIT_EVENT_DSM_FILL_ZERO_WRITE,
899 WAIT_EVENT_LOCK_FILE_ADDTODATADIR_READ,
900 WAIT_EVENT_LOCK_FILE_ADDTODATADIR_SYNC,
901 WAIT_EVENT_LOCK_FILE_ADDTODATADIR_WRITE,
902 WAIT_EVENT_LOCK_FILE_CREATE_READ,
903 WAIT_EVENT_LOCK_FILE_CREATE_SYNC,
904 WAIT_EVENT_LOCK_FILE_CREATE_WRITE,
905 WAIT_EVENT_LOCK_FILE_RECHECKDATADIR_READ,
906 WAIT_EVENT_LOGICAL_REWRITE_CHECKPOINT_SYNC,
907 WAIT_EVENT_LOGICAL_REWRITE_MAPPING_SYNC,
908 WAIT_EVENT_LOGICAL_REWRITE_MAPPING_WRITE,
909 WAIT_EVENT_LOGICAL_REWRITE_SYNC,
910 WAIT_EVENT_LOGICAL_REWRITE_TRUNCATE,
911 WAIT_EVENT_LOGICAL_REWRITE_WRITE,
912 WAIT_EVENT_RELATION_MAP_READ,
913 WAIT_EVENT_RELATION_MAP_SYNC,
914 WAIT_EVENT_RELATION_MAP_WRITE,
915 WAIT_EVENT_REORDER_BUFFER_READ,
916 WAIT_EVENT_REORDER_BUFFER_WRITE,
917 WAIT_EVENT_REORDER_LOGICAL_MAPPING_READ,
918 WAIT_EVENT_REPLICATION_SLOT_READ,
919 WAIT_EVENT_REPLICATION_SLOT_RESTORE_SYNC,
920 WAIT_EVENT_REPLICATION_SLOT_SYNC,
921 WAIT_EVENT_REPLICATION_SLOT_WRITE,
922 WAIT_EVENT_SLRU_FLUSH_SYNC,
923 WAIT_EVENT_SLRU_READ,
924 WAIT_EVENT_SLRU_SYNC,
925 WAIT_EVENT_SLRU_WRITE,
926 WAIT_EVENT_SNAPBUILD_READ,
927 WAIT_EVENT_SNAPBUILD_SYNC,
928 WAIT_EVENT_SNAPBUILD_WRITE,
929 WAIT_EVENT_TIMELINE_HISTORY_FILE_SYNC,
930 WAIT_EVENT_TIMELINE_HISTORY_FILE_WRITE,
931 WAIT_EVENT_TIMELINE_HISTORY_READ,
932 WAIT_EVENT_TIMELINE_HISTORY_SYNC,
933 WAIT_EVENT_TIMELINE_HISTORY_WRITE,
934 WAIT_EVENT_TWOPHASE_FILE_READ,
935 WAIT_EVENT_TWOPHASE_FILE_SYNC,
936 WAIT_EVENT_TWOPHASE_FILE_WRITE,
937 WAIT_EVENT_WALSENDER_TIMELINE_HISTORY_READ,
938 WAIT_EVENT_WAL_BOOTSTRAP_SYNC,
939 WAIT_EVENT_WAL_BOOTSTRAP_WRITE,
940 WAIT_EVENT_WAL_COPY_READ,
941 WAIT_EVENT_WAL_COPY_SYNC,
942 WAIT_EVENT_WAL_COPY_WRITE,
943 WAIT_EVENT_WAL_INIT_SYNC,
944 WAIT_EVENT_WAL_INIT_WRITE,
945 WAIT_EVENT_WAL_READ,
946 WAIT_EVENT_WAL_SYNC,
947 WAIT_EVENT_WAL_SYNC_METHOD_ASSIGN,
948 WAIT_EVENT_WAL_WRITE
949} WaitEventIO;
950
951/* ----------
952 * Command type for progress reporting purposes
953 * ----------
954 */
955typedef enum ProgressCommandType
956{
957 PROGRESS_COMMAND_INVALID,
958 PROGRESS_COMMAND_VACUUM,
959 PROGRESS_COMMAND_CLUSTER,
960 PROGRESS_COMMAND_CREATE_INDEX
961} ProgressCommandType;
962
963#define PGSTAT_NUM_PROGRESS_PARAM 20
964
965/* ----------
966 * Shared-memory data structures
967 * ----------
968 */
969
970
971/*
972 * PgBackendSSLStatus
973 *
974 * For each backend, we keep the SSL status in a separate struct, that
975 * is only filled in if SSL is enabled.
976 *
977 * All char arrays must be null-terminated.
978 */
979typedef struct PgBackendSSLStatus
980{
981 /* Information about SSL connection */
982 int ssl_bits;
983 bool ssl_compression;
984 char ssl_version[NAMEDATALEN];
985 char ssl_cipher[NAMEDATALEN];
986 char ssl_client_dn[NAMEDATALEN];
987
988 /*
989 * serial number is max "20 octets" per RFC 5280, so this size should be
990 * fine
991 */
992 char ssl_client_serial[NAMEDATALEN];
993
994 char ssl_issuer_dn[NAMEDATALEN];
995} PgBackendSSLStatus;
996
997/*
998 * PgBackendGSSStatus
999 *
1000 * For each backend, we keep the GSS status in a separate struct, that
1001 * is only filled in if GSS is enabled.
1002 *
1003 * All char arrays must be null-terminated.
1004 */
1005typedef struct PgBackendGSSStatus
1006{
1007 /* Information about GSSAPI connection */
1008 char gss_princ[NAMEDATALEN]; /* GSSAPI Principal used to auth */
1009 bool gss_auth; /* If GSSAPI authentication was used */
1010 bool gss_enc; /* If encryption is being used */
1011
1012} PgBackendGSSStatus;
1013
1014
1015/* ----------
1016 * PgBackendStatus
1017 *
1018 * Each live backend maintains a PgBackendStatus struct in shared memory
1019 * showing its current activity. (The structs are allocated according to
1020 * BackendId, but that is not critical.) Note that the collector process
1021 * has no involvement in, or even access to, these structs.
1022 *
1023 * Each auxiliary process also maintains a PgBackendStatus struct in shared
1024 * memory.
1025 * ----------
1026 */
1027typedef struct PgBackendStatus
1028{
1029 /*
1030 * To avoid locking overhead, we use the following protocol: a backend
1031 * increments st_changecount before modifying its entry, and again after
1032 * finishing a modification. A would-be reader should note the value of
1033 * st_changecount, copy the entry into private memory, then check
1034 * st_changecount again. If the value hasn't changed, and if it's even,
1035 * the copy is valid; otherwise start over. This makes updates cheap
1036 * while reads are potentially expensive, but that's the tradeoff we want.
1037 *
1038 * The above protocol needs memory barriers to ensure that the apparent
1039 * order of execution is as it desires. Otherwise, for example, the CPU
1040 * might rearrange the code so that st_changecount is incremented twice
1041 * before the modification on a machine with weak memory ordering. Hence,
1042 * use the macros defined below for manipulating st_changecount, rather
1043 * than touching it directly.
1044 */
1045 int st_changecount;
1046
1047 /* The entry is valid iff st_procpid > 0, unused if st_procpid == 0 */
1048 int st_procpid;
1049
1050 /* Type of backends */
1051 BackendType st_backendType;
1052
1053 /* Times when current backend, transaction, and activity started */
1054 TimestampTz st_proc_start_timestamp;
1055 TimestampTz st_xact_start_timestamp;
1056 TimestampTz st_activity_start_timestamp;
1057 TimestampTz st_state_start_timestamp;
1058
1059 /* Database OID, owning user's OID, connection client address */
1060 Oid st_databaseid;
1061 Oid st_userid;
1062 SockAddr st_clientaddr;
1063 char *st_clienthostname; /* MUST be null-terminated */
1064
1065 /* Information about SSL connection */
1066 bool st_ssl;
1067 PgBackendSSLStatus *st_sslstatus;
1068
1069 /* Information about GSSAPI connection */
1070 bool st_gss;
1071 PgBackendGSSStatus *st_gssstatus;
1072
1073 /* current state */
1074 BackendState st_state;
1075
1076 /* application name; MUST be null-terminated */
1077 char *st_appname;
1078
1079 /*
1080 * Current command string; MUST be null-terminated. Note that this string
1081 * possibly is truncated in the middle of a multi-byte character. As
1082 * activity strings are stored more frequently than read, that allows to
1083 * move the cost of correct truncation to the display side. Use
1084 * pgstat_clip_activity() to truncate correctly.
1085 */
1086 char *st_activity_raw;
1087
1088 /*
1089 * Command progress reporting. Any command which wishes can advertise
1090 * that it is running by setting st_progress_command,
1091 * st_progress_command_target, and st_progress_param[].
1092 * st_progress_command_target should be the OID of the relation which the
1093 * command targets (we assume there's just one, as this is meant for
1094 * utility commands), but the meaning of each element in the
1095 * st_progress_param array is command-specific.
1096 */
1097 ProgressCommandType st_progress_command;
1098 Oid st_progress_command_target;
1099 int64 st_progress_param[PGSTAT_NUM_PROGRESS_PARAM];
1100} PgBackendStatus;
1101
1102/*
1103 * Macros to load and store st_changecount with appropriate memory barriers.
1104 *
1105 * Use PGSTAT_BEGIN_WRITE_ACTIVITY() before, and PGSTAT_END_WRITE_ACTIVITY()
1106 * after, modifying the current process's PgBackendStatus data. Note that,
1107 * since there is no mechanism for cleaning up st_changecount after an error,
1108 * THESE MACROS FORM A CRITICAL SECTION. Any error between them will be
1109 * promoted to PANIC, causing a database restart to clean up shared memory!
1110 * Hence, keep the critical section as short and straight-line as possible.
1111 * Aside from being safer, that minimizes the window in which readers will
1112 * have to loop.
1113 *
1114 * Reader logic should follow this sketch:
1115 *
1116 * for (;;)
1117 * {
1118 * int before_ct, after_ct;
1119 *
1120 * pgstat_begin_read_activity(beentry, before_ct);
1121 * ... copy beentry data to local memory ...
1122 * pgstat_end_read_activity(beentry, after_ct);
1123 * if (pgstat_read_activity_complete(before_ct, after_ct))
1124 * break;
1125 * CHECK_FOR_INTERRUPTS();
1126 * }
1127 *
1128 * For extra safety, we generally use volatile beentry pointers, although
1129 * the memory barriers should theoretically be sufficient.
1130 */
1131#define PGSTAT_BEGIN_WRITE_ACTIVITY(beentry) \
1132 do { \
1133 START_CRIT_SECTION(); \
1134 (beentry)->st_changecount++; \
1135 pg_write_barrier(); \
1136 } while (0)
1137
1138#define PGSTAT_END_WRITE_ACTIVITY(beentry) \
1139 do { \
1140 pg_write_barrier(); \
1141 (beentry)->st_changecount++; \
1142 Assert(((beentry)->st_changecount & 1) == 0); \
1143 END_CRIT_SECTION(); \
1144 } while (0)
1145
1146#define pgstat_begin_read_activity(beentry, before_changecount) \
1147 do { \
1148 (before_changecount) = (beentry)->st_changecount; \
1149 pg_read_barrier(); \
1150 } while (0)
1151
1152#define pgstat_end_read_activity(beentry, after_changecount) \
1153 do { \
1154 pg_read_barrier(); \
1155 (after_changecount) = (beentry)->st_changecount; \
1156 } while (0)
1157
1158#define pgstat_read_activity_complete(before_changecount, after_changecount) \
1159 ((before_changecount) == (after_changecount) && \
1160 ((before_changecount) & 1) == 0)
1161
1162
1163/* ----------
1164 * LocalPgBackendStatus
1165 *
1166 * When we build the backend status array, we use LocalPgBackendStatus to be
1167 * able to add new values to the struct when needed without adding new fields
1168 * to the shared memory. It contains the backend status as a first member.
1169 * ----------
1170 */
1171typedef struct LocalPgBackendStatus
1172{
1173 /*
1174 * Local version of the backend status entry.
1175 */
1176 PgBackendStatus backendStatus;
1177
1178 /*
1179 * The xid of the current transaction if available, InvalidTransactionId
1180 * if not.
1181 */
1182 TransactionId backend_xid;
1183
1184 /*
1185 * The xmin of the current session if available, InvalidTransactionId if
1186 * not.
1187 */
1188 TransactionId backend_xmin;
1189} LocalPgBackendStatus;
1190
1191/*
1192 * Working state needed to accumulate per-function-call timing statistics.
1193 */
1194typedef struct PgStat_FunctionCallUsage
1195{
1196 /* Link to function's hashtable entry (must still be there at exit!) */
1197 /* NULL means we are not tracking the current function call */
1198 PgStat_FunctionCounts *fs;
1199 /* Total time previously charged to function, as of function start */
1200 instr_time save_f_total_time;
1201 /* Backend-wide total time as of function start */
1202 instr_time save_total;
1203 /* system clock as of function start */
1204 instr_time f_start;
1205} PgStat_FunctionCallUsage;
1206
1207
1208/* ----------
1209 * GUC parameters
1210 * ----------
1211 */
1212extern bool pgstat_track_activities;
1213extern bool pgstat_track_counts;
1214extern int pgstat_track_functions;
1215extern PGDLLIMPORT int pgstat_track_activity_query_size;
1216extern char *pgstat_stat_directory;
1217extern char *pgstat_stat_tmpname;
1218extern char *pgstat_stat_filename;
1219
1220/*
1221 * BgWriter statistics counters are updated directly by bgwriter and bufmgr
1222 */
1223extern PgStat_MsgBgWriter BgWriterStats;
1224
1225/*
1226 * Updated by pgstat_count_buffer_*_time macros
1227 */
1228extern PgStat_Counter pgStatBlockReadTime;
1229extern PgStat_Counter pgStatBlockWriteTime;
1230
1231/* ----------
1232 * Functions called from postmaster
1233 * ----------
1234 */
1235extern Size BackendStatusShmemSize(void);
1236extern void CreateSharedBackendStatus(void);
1237
1238extern void pgstat_init(void);
1239extern int pgstat_start(void);
1240extern void pgstat_reset_all(void);
1241extern void allow_immediate_pgstat_restart(void);
1242
1243#ifdef EXEC_BACKEND
1244extern void PgstatCollectorMain(int argc, char *argv[]) pg_attribute_noreturn();
1245#endif
1246
1247
1248/* ----------
1249 * Functions called from backends
1250 * ----------
1251 */
1252extern void pgstat_ping(void);
1253
1254extern void pgstat_report_stat(bool force);
1255extern void pgstat_vacuum_stat(void);
1256extern void pgstat_drop_database(Oid databaseid);
1257
1258extern void pgstat_clear_snapshot(void);
1259extern void pgstat_reset_counters(void);
1260extern void pgstat_reset_shared_counters(const char *);
1261extern void pgstat_reset_single_counter(Oid objectid, PgStat_Single_Reset_Type type);
1262
1263extern void pgstat_report_autovac(Oid dboid);
1264extern void pgstat_report_vacuum(Oid tableoid, bool shared,
1265 PgStat_Counter livetuples, PgStat_Counter deadtuples);
1266extern void pgstat_report_analyze(Relation rel,
1267 PgStat_Counter livetuples, PgStat_Counter deadtuples,
1268 bool resetcounter);
1269
1270extern void pgstat_report_recovery_conflict(int reason);
1271extern void pgstat_report_deadlock(void);
1272extern void pgstat_report_checksum_failures_in_db(Oid dboid, int failurecount);
1273extern void pgstat_report_checksum_failure(void);
1274
1275extern void pgstat_initialize(void);
1276extern void pgstat_bestart(void);
1277
1278extern void pgstat_report_activity(BackendState state, const char *cmd_str);
1279extern void pgstat_report_tempfile(size_t filesize);
1280extern void pgstat_report_appname(const char *appname);
1281extern void pgstat_report_xact_timestamp(TimestampTz tstamp);
1282extern const char *pgstat_get_wait_event(uint32 wait_event_info);
1283extern const char *pgstat_get_wait_event_type(uint32 wait_event_info);
1284extern const char *pgstat_get_backend_current_activity(int pid, bool checkUser);
1285extern const char *pgstat_get_crashed_backend_activity(int pid, char *buffer,
1286 int buflen);
1287extern const char *pgstat_get_backend_desc(BackendType backendType);
1288
1289extern void pgstat_progress_start_command(ProgressCommandType cmdtype,
1290 Oid relid);
1291extern void pgstat_progress_update_param(int index, int64 val);
1292extern void pgstat_progress_update_multi_param(int nparam, const int *index,
1293 const int64 *val);
1294extern void pgstat_progress_end_command(void);
1295
1296extern PgStat_TableStatus *find_tabstat_entry(Oid rel_id);
1297extern PgStat_BackendFunctionEntry *find_funcstat_entry(Oid func_id);
1298
1299extern void pgstat_initstats(Relation rel);
1300
1301extern char *pgstat_clip_activity(const char *raw_activity);
1302
1303/* ----------
1304 * pgstat_report_wait_start() -
1305 *
1306 * Called from places where server process needs to wait. This is called
1307 * to report wait event information. The wait information is stored
1308 * as 4-bytes where first byte represents the wait event class (type of
1309 * wait, for different types of wait, refer WaitClass) and the next
1310 * 3-bytes represent the actual wait event. Currently 2-bytes are used
1311 * for wait event which is sufficient for current usage, 1-byte is
1312 * reserved for future usage.
1313 *
1314 * NB: this *must* be able to survive being called before MyProc has been
1315 * initialized.
1316 * ----------
1317 */
1318static inline void
1319pgstat_report_wait_start(uint32 wait_event_info)
1320{
1321 volatile PGPROC *proc = MyProc;
1322
1323 if (!pgstat_track_activities || !proc)
1324 return;
1325
1326 /*
1327 * Since this is a four-byte field which is always read and written as
1328 * four-bytes, updates are atomic.
1329 */
1330 proc->wait_event_info = wait_event_info;
1331}
1332
1333/* ----------
1334 * pgstat_report_wait_end() -
1335 *
1336 * Called to report end of a wait.
1337 *
1338 * NB: this *must* be able to survive being called before MyProc has been
1339 * initialized.
1340 * ----------
1341 */
1342static inline void
1343pgstat_report_wait_end(void)
1344{
1345 volatile PGPROC *proc = MyProc;
1346
1347 if (!pgstat_track_activities || !proc)
1348 return;
1349
1350 /*
1351 * Since this is a four-byte field which is always read and written as
1352 * four-bytes, updates are atomic.
1353 */
1354 proc->wait_event_info = 0;
1355}
1356
1357/* nontransactional event counts are simple enough to inline */
1358
1359#define pgstat_count_heap_scan(rel) \
1360 do { \
1361 if ((rel)->pgstat_info != NULL) \
1362 (rel)->pgstat_info->t_counts.t_numscans++; \
1363 } while (0)
1364#define pgstat_count_heap_getnext(rel) \
1365 do { \
1366 if ((rel)->pgstat_info != NULL) \
1367 (rel)->pgstat_info->t_counts.t_tuples_returned++; \
1368 } while (0)
1369#define pgstat_count_heap_fetch(rel) \
1370 do { \
1371 if ((rel)->pgstat_info != NULL) \
1372 (rel)->pgstat_info->t_counts.t_tuples_fetched++; \
1373 } while (0)
1374#define pgstat_count_index_scan(rel) \
1375 do { \
1376 if ((rel)->pgstat_info != NULL) \
1377 (rel)->pgstat_info->t_counts.t_numscans++; \
1378 } while (0)
1379#define pgstat_count_index_tuples(rel, n) \
1380 do { \
1381 if ((rel)->pgstat_info != NULL) \
1382 (rel)->pgstat_info->t_counts.t_tuples_returned += (n); \
1383 } while (0)
1384#define pgstat_count_buffer_read(rel) \
1385 do { \
1386 if ((rel)->pgstat_info != NULL) \
1387 (rel)->pgstat_info->t_counts.t_blocks_fetched++; \
1388 } while (0)
1389#define pgstat_count_buffer_hit(rel) \
1390 do { \
1391 if ((rel)->pgstat_info != NULL) \
1392 (rel)->pgstat_info->t_counts.t_blocks_hit++; \
1393 } while (0)
1394#define pgstat_count_buffer_read_time(n) \
1395 (pgStatBlockReadTime += (n))
1396#define pgstat_count_buffer_write_time(n) \
1397 (pgStatBlockWriteTime += (n))
1398
1399extern void pgstat_count_heap_insert(Relation rel, PgStat_Counter n);
1400extern void pgstat_count_heap_update(Relation rel, bool hot);
1401extern void pgstat_count_heap_delete(Relation rel);
1402extern void pgstat_count_truncate(Relation rel);
1403extern void pgstat_update_heap_dead_tuples(Relation rel, int delta);
1404
1405extern void pgstat_init_function_usage(FunctionCallInfo fcinfo,
1406 PgStat_FunctionCallUsage *fcu);
1407extern void pgstat_end_function_usage(PgStat_FunctionCallUsage *fcu,
1408 bool finalize);
1409
1410extern void AtEOXact_PgStat(bool isCommit, bool parallel);
1411extern void AtEOSubXact_PgStat(bool isCommit, int nestDepth);
1412
1413extern void AtPrepare_PgStat(void);
1414extern void PostPrepare_PgStat(void);
1415
1416extern void pgstat_twophase_postcommit(TransactionId xid, uint16 info,
1417 void *recdata, uint32 len);
1418extern void pgstat_twophase_postabort(TransactionId xid, uint16 info,
1419 void *recdata, uint32 len);
1420
1421extern void pgstat_send_archiver(const char *xlog, bool failed);
1422extern void pgstat_send_bgwriter(void);
1423
1424/* ----------
1425 * Support functions for the SQL-callable functions to
1426 * generate the pgstat* views.
1427 * ----------
1428 */
1429extern PgStat_StatDBEntry *pgstat_fetch_stat_dbentry(Oid dbid);
1430extern PgStat_StatTabEntry *pgstat_fetch_stat_tabentry(Oid relid);
1431extern PgBackendStatus *pgstat_fetch_stat_beentry(int beid);
1432extern LocalPgBackendStatus *pgstat_fetch_stat_local_beentry(int beid);
1433extern PgStat_StatFuncEntry *pgstat_fetch_stat_funcentry(Oid funcid);
1434extern int pgstat_fetch_stat_numbackends(void);
1435extern PgStat_ArchiverStats *pgstat_fetch_stat_archiver(void);
1436extern PgStat_GlobalStats *pgstat_fetch_global(void);
1437
1438#endif /* PGSTAT_H */
1439