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