]> granicus.if.org Git - postgresql/blob - src/include/pgstat.h
Add assertion to check the special size is sane before dereferencing it.
[postgresql] / src / include / pgstat.h
1 /* ----------
2  *      pgstat.h
3  *
4  *      Definitions for the PostgreSQL statistics collector daemon.
5  *
6  *      Copyright (c) 2001-2015, 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 "portability/instr_time.h"
18 #include "postmaster/pgarch.h"
19 #include "storage/barrier.h"
20 #include "utils/hsearch.h"
21 #include "utils/relcache.h"
22
23
24 /* ----------
25  * Paths for the statistics files (relative to installation's $PGDATA).
26  * ----------
27  */
28 #define PGSTAT_STAT_PERMANENT_DIRECTORY         "pg_stat"
29 #define PGSTAT_STAT_PERMANENT_FILENAME          "pg_stat/global.stat"
30 #define PGSTAT_STAT_PERMANENT_TMPFILE           "pg_stat/global.tmp"
31
32 /* Default directory to store temporary statistics data in */
33 #define PG_STAT_TMP_DIR         "pg_stat_tmp"
34
35 /* Values for track_functions GUC variable --- order is significant! */
36 typedef enum TrackFunctionsLevel
37 {
38         TRACK_FUNC_OFF,
39         TRACK_FUNC_PL,
40         TRACK_FUNC_ALL
41 }       TrackFunctionsLevel;
42
43 /* ----------
44  * The types of backend -> collector messages
45  * ----------
46  */
47 typedef enum StatMsgType
48 {
49         PGSTAT_MTYPE_DUMMY,
50         PGSTAT_MTYPE_INQUIRY,
51         PGSTAT_MTYPE_TABSTAT,
52         PGSTAT_MTYPE_TABPURGE,
53         PGSTAT_MTYPE_DROPDB,
54         PGSTAT_MTYPE_RESETCOUNTER,
55         PGSTAT_MTYPE_RESETSHAREDCOUNTER,
56         PGSTAT_MTYPE_RESETSINGLECOUNTER,
57         PGSTAT_MTYPE_AUTOVAC_START,
58         PGSTAT_MTYPE_VACUUM,
59         PGSTAT_MTYPE_ANALYZE,
60         PGSTAT_MTYPE_ARCHIVER,
61         PGSTAT_MTYPE_BGWRITER,
62         PGSTAT_MTYPE_FUNCSTAT,
63         PGSTAT_MTYPE_FUNCPURGE,
64         PGSTAT_MTYPE_RECOVERYCONFLICT,
65         PGSTAT_MTYPE_TEMPFILE,
66         PGSTAT_MTYPE_DEADLOCK
67 } StatMsgType;
68
69 /* ----------
70  * The data type used for counters.
71  * ----------
72  */
73 typedef int64 PgStat_Counter;
74
75 /* ----------
76  * PgStat_TableCounts                   The actual per-table counts kept by a backend
77  *
78  * This struct should contain only actual event counters, because we memcmp
79  * it against zeroes to detect whether there are any counts to transmit.
80  * It is a component of PgStat_TableStatus (within-backend state) and
81  * PgStat_TableEntry (the transmitted message format).
82  *
83  * Note: for a table, tuples_returned is the number of tuples successfully
84  * fetched by heap_getnext, while tuples_fetched is the number of tuples
85  * successfully fetched by heap_fetch under the control of bitmap indexscans.
86  * For an index, tuples_returned is the number of index entries returned by
87  * the index AM, while tuples_fetched is the number of tuples successfully
88  * fetched by heap_fetch under the control of simple indexscans for this index.
89  *
90  * tuples_inserted/updated/deleted/hot_updated count attempted actions,
91  * regardless of whether the transaction committed.  delta_live_tuples,
92  * delta_dead_tuples, and changed_tuples are set depending on commit or abort.
93  * Note that delta_live_tuples and delta_dead_tuples can be negative!
94  * ----------
95  */
96 typedef struct PgStat_TableCounts
97 {
98         PgStat_Counter t_numscans;
99
100         PgStat_Counter t_tuples_returned;
101         PgStat_Counter t_tuples_fetched;
102
103         PgStat_Counter t_tuples_inserted;
104         PgStat_Counter t_tuples_updated;
105         PgStat_Counter t_tuples_deleted;
106         PgStat_Counter t_tuples_hot_updated;
107         bool            t_truncated;
108
109         PgStat_Counter t_delta_live_tuples;
110         PgStat_Counter t_delta_dead_tuples;
111         PgStat_Counter t_changed_tuples;
112
113         PgStat_Counter t_blocks_fetched;
114         PgStat_Counter t_blocks_hit;
115 } PgStat_TableCounts;
116
117 /* Possible targets for resetting cluster-wide shared values */
118 typedef enum PgStat_Shared_Reset_Target
119 {
120         RESET_ARCHIVER,
121         RESET_BGWRITER
122 } PgStat_Shared_Reset_Target;
123
124 /* Possible object types for resetting single counters */
125 typedef enum PgStat_Single_Reset_Type
126 {
127         RESET_TABLE,
128         RESET_FUNCTION
129 } PgStat_Single_Reset_Type;
130
131 /* ------------------------------------------------------------
132  * Structures kept in backend local memory while accumulating counts
133  * ------------------------------------------------------------
134  */
135
136
137 /* ----------
138  * PgStat_TableStatus                   Per-table status within a backend
139  *
140  * Many of the event counters are nontransactional, ie, we count events
141  * in committed and aborted transactions alike.  For these, we just count
142  * directly in the PgStat_TableStatus.  However, delta_live_tuples,
143  * delta_dead_tuples, and changed_tuples must be derived from event counts
144  * with awareness of whether the transaction or subtransaction committed or
145  * aborted.  Hence, we also keep a stack of per-(sub)transaction status
146  * records for every table modified in the current transaction.  At commit
147  * or abort, we propagate tuples_inserted/updated/deleted up to the
148  * parent subtransaction level, or out to the parent PgStat_TableStatus,
149  * as appropriate.
150  * ----------
151  */
152 typedef struct PgStat_TableStatus
153 {
154         Oid                     t_id;                   /* table's OID */
155         bool            t_shared;               /* is it a shared catalog? */
156         struct PgStat_TableXactStatus *trans;           /* lowest subxact's counts */
157         PgStat_TableCounts t_counts;    /* event counts to be sent */
158 } PgStat_TableStatus;
159
160 /* ----------
161  * PgStat_TableXactStatus               Per-table, per-subtransaction status
162  * ----------
163  */
164 typedef struct PgStat_TableXactStatus
165 {
166         PgStat_Counter tuples_inserted;         /* tuples inserted in (sub)xact */
167         PgStat_Counter tuples_updated;          /* tuples updated in (sub)xact */
168         PgStat_Counter tuples_deleted;          /* tuples deleted in (sub)xact */
169         bool            truncated;              /* relation truncated in this (sub)xact */
170         PgStat_Counter inserted_pre_trunc;      /* tuples inserted prior to truncate */
171         PgStat_Counter updated_pre_trunc;       /* tuples updated prior to truncate */
172         PgStat_Counter deleted_pre_trunc;       /* tuples deleted prior to truncate */
173         int                     nest_level;             /* subtransaction nest level */
174         /* links to other structs for same relation: */
175         struct PgStat_TableXactStatus *upper;           /* next higher subxact if any */
176         PgStat_TableStatus *parent; /* per-table status */
177         /* structs of same subxact level are linked here: */
178         struct PgStat_TableXactStatus *next;            /* next of same subxact */
179 } PgStat_TableXactStatus;
180
181
182 /* ------------------------------------------------------------
183  * Message formats follow
184  * ------------------------------------------------------------
185  */
186
187
188 /* ----------
189  * PgStat_MsgHdr                                The common message header
190  * ----------
191  */
192 typedef struct PgStat_MsgHdr
193 {
194         StatMsgType m_type;
195         int                     m_size;
196 } PgStat_MsgHdr;
197
198 /* ----------
199  * Space available in a message.  This will keep the UDP packets below 1K,
200  * which should fit unfragmented into the MTU of the loopback interface.
201  * (Larger values of PGSTAT_MAX_MSG_SIZE would work for that on most
202  * platforms, but we're being conservative here.)
203  * ----------
204  */
205 #define PGSTAT_MAX_MSG_SIZE 1000
206 #define PGSTAT_MSG_PAYLOAD      (PGSTAT_MAX_MSG_SIZE - sizeof(PgStat_MsgHdr))
207
208
209 /* ----------
210  * PgStat_MsgDummy                              A dummy message, ignored by the collector
211  * ----------
212  */
213 typedef struct PgStat_MsgDummy
214 {
215         PgStat_MsgHdr m_hdr;
216 } PgStat_MsgDummy;
217
218
219 /* ----------
220  * PgStat_MsgInquiry                    Sent by a backend to ask the collector
221  *                                                              to write the stats file.
222  * ----------
223  */
224
225 typedef struct PgStat_MsgInquiry
226 {
227         PgStat_MsgHdr m_hdr;
228         TimestampTz clock_time;         /* observed local clock time */
229         TimestampTz cutoff_time;        /* minimum acceptable file timestamp */
230         Oid                     databaseid;             /* requested DB (InvalidOid => all DBs) */
231 } PgStat_MsgInquiry;
232
233
234 /* ----------
235  * PgStat_TableEntry                    Per-table info in a MsgTabstat
236  * ----------
237  */
238 typedef struct PgStat_TableEntry
239 {
240         Oid                     t_id;
241         PgStat_TableCounts t_counts;
242 } PgStat_TableEntry;
243
244 /* ----------
245  * PgStat_MsgTabstat                    Sent by the backend to report table
246  *                                                              and buffer access statistics.
247  * ----------
248  */
249 #define PGSTAT_NUM_TABENTRIES  \
250         ((PGSTAT_MSG_PAYLOAD - sizeof(Oid) - 3 * sizeof(int) - 2 * sizeof(PgStat_Counter))      \
251          / sizeof(PgStat_TableEntry))
252
253 typedef struct PgStat_MsgTabstat
254 {
255         PgStat_MsgHdr m_hdr;
256         Oid                     m_databaseid;
257         int                     m_nentries;
258         int                     m_xact_commit;
259         int                     m_xact_rollback;
260         PgStat_Counter m_block_read_time;       /* times in microseconds */
261         PgStat_Counter m_block_write_time;
262         PgStat_TableEntry m_entry[PGSTAT_NUM_TABENTRIES];
263 } PgStat_MsgTabstat;
264
265
266 /* ----------
267  * PgStat_MsgTabpurge                   Sent by the backend to tell the collector
268  *                                                              about dead tables.
269  * ----------
270  */
271 #define PGSTAT_NUM_TABPURGE  \
272         ((PGSTAT_MSG_PAYLOAD - sizeof(Oid) - sizeof(int))  \
273          / sizeof(Oid))
274
275 typedef struct PgStat_MsgTabpurge
276 {
277         PgStat_MsgHdr m_hdr;
278         Oid                     m_databaseid;
279         int                     m_nentries;
280         Oid                     m_tableid[PGSTAT_NUM_TABPURGE];
281 } PgStat_MsgTabpurge;
282
283
284 /* ----------
285  * PgStat_MsgDropdb                             Sent by the backend to tell the collector
286  *                                                              about a dropped database
287  * ----------
288  */
289 typedef struct PgStat_MsgDropdb
290 {
291         PgStat_MsgHdr m_hdr;
292         Oid                     m_databaseid;
293 } PgStat_MsgDropdb;
294
295
296 /* ----------
297  * PgStat_MsgResetcounter               Sent by the backend to tell the collector
298  *                                                              to reset counters
299  * ----------
300  */
301 typedef struct PgStat_MsgResetcounter
302 {
303         PgStat_MsgHdr m_hdr;
304         Oid                     m_databaseid;
305 } PgStat_MsgResetcounter;
306
307 /* ----------
308  * PgStat_MsgResetsharedcounter Sent by the backend to tell the collector
309  *                                                              to reset a shared counter
310  * ----------
311  */
312 typedef struct PgStat_MsgResetsharedcounter
313 {
314         PgStat_MsgHdr m_hdr;
315         PgStat_Shared_Reset_Target m_resettarget;
316 } PgStat_MsgResetsharedcounter;
317
318 /* ----------
319  * PgStat_MsgResetsinglecounter Sent by the backend to tell the collector
320  *                                                              to reset a single counter
321  * ----------
322  */
323 typedef struct PgStat_MsgResetsinglecounter
324 {
325         PgStat_MsgHdr m_hdr;
326         Oid                     m_databaseid;
327         PgStat_Single_Reset_Type m_resettype;
328         Oid                     m_objectid;
329 } PgStat_MsgResetsinglecounter;
330
331 /* ----------
332  * PgStat_MsgAutovacStart               Sent by the autovacuum daemon to signal
333  *                                                              that a database is going to be processed
334  * ----------
335  */
336 typedef struct PgStat_MsgAutovacStart
337 {
338         PgStat_MsgHdr m_hdr;
339         Oid                     m_databaseid;
340         TimestampTz m_start_time;
341 } PgStat_MsgAutovacStart;
342
343
344 /* ----------
345  * PgStat_MsgVacuum                             Sent by the backend or autovacuum daemon
346  *                                                              after VACUUM
347  * ----------
348  */
349 typedef struct PgStat_MsgVacuum
350 {
351         PgStat_MsgHdr m_hdr;
352         Oid                     m_databaseid;
353         Oid                     m_tableoid;
354         bool            m_autovacuum;
355         TimestampTz m_vacuumtime;
356         PgStat_Counter m_live_tuples;
357         PgStat_Counter m_dead_tuples;
358 } PgStat_MsgVacuum;
359
360
361 /* ----------
362  * PgStat_MsgAnalyze                    Sent by the backend or autovacuum daemon
363  *                                                              after ANALYZE
364  * ----------
365  */
366 typedef struct PgStat_MsgAnalyze
367 {
368         PgStat_MsgHdr m_hdr;
369         Oid                     m_databaseid;
370         Oid                     m_tableoid;
371         bool            m_autovacuum;
372         TimestampTz m_analyzetime;
373         PgStat_Counter m_live_tuples;
374         PgStat_Counter m_dead_tuples;
375 } PgStat_MsgAnalyze;
376
377
378 /* ----------
379  * PgStat_MsgArchiver                   Sent by the archiver to update statistics.
380  * ----------
381  */
382 typedef struct PgStat_MsgArchiver
383 {
384         PgStat_MsgHdr m_hdr;
385         bool            m_failed;               /* Failed attempt */
386         char            m_xlog[MAX_XFN_CHARS + 1];
387         TimestampTz m_timestamp;
388 } PgStat_MsgArchiver;
389
390 /* ----------
391  * PgStat_MsgBgWriter                   Sent by the bgwriter to update statistics.
392  * ----------
393  */
394 typedef struct PgStat_MsgBgWriter
395 {
396         PgStat_MsgHdr m_hdr;
397
398         PgStat_Counter m_timed_checkpoints;
399         PgStat_Counter m_requested_checkpoints;
400         PgStat_Counter m_buf_written_checkpoints;
401         PgStat_Counter m_buf_written_clean;
402         PgStat_Counter m_maxwritten_clean;
403         PgStat_Counter m_buf_written_backend;
404         PgStat_Counter m_buf_fsync_backend;
405         PgStat_Counter m_buf_alloc;
406         PgStat_Counter m_checkpoint_write_time;         /* times in milliseconds */
407         PgStat_Counter m_checkpoint_sync_time;
408 } PgStat_MsgBgWriter;
409
410 /* ----------
411  * PgStat_MsgRecoveryConflict   Sent by the backend upon recovery conflict
412  * ----------
413  */
414 typedef struct PgStat_MsgRecoveryConflict
415 {
416         PgStat_MsgHdr m_hdr;
417
418         Oid                     m_databaseid;
419         int                     m_reason;
420 } PgStat_MsgRecoveryConflict;
421
422 /* ----------
423  * PgStat_MsgTempFile   Sent by the backend upon creating a temp file
424  * ----------
425  */
426 typedef struct PgStat_MsgTempFile
427 {
428         PgStat_MsgHdr m_hdr;
429
430         Oid                     m_databaseid;
431         size_t          m_filesize;
432 } PgStat_MsgTempFile;
433
434 /* ----------
435  * PgStat_FunctionCounts        The actual per-function counts kept by a backend
436  *
437  * This struct should contain only actual event counters, because we memcmp
438  * it against zeroes to detect whether there are any counts to transmit.
439  *
440  * Note that the time counters are in instr_time format here.  We convert to
441  * microseconds in PgStat_Counter format when transmitting to the collector.
442  * ----------
443  */
444 typedef struct PgStat_FunctionCounts
445 {
446         PgStat_Counter f_numcalls;
447         instr_time      f_total_time;
448         instr_time      f_self_time;
449 } PgStat_FunctionCounts;
450
451 /* ----------
452  * PgStat_BackendFunctionEntry  Entry in backend's per-function hash table
453  * ----------
454  */
455 typedef struct PgStat_BackendFunctionEntry
456 {
457         Oid                     f_id;
458         PgStat_FunctionCounts f_counts;
459 } PgStat_BackendFunctionEntry;
460
461 /* ----------
462  * PgStat_FunctionEntry                 Per-function info in a MsgFuncstat
463  * ----------
464  */
465 typedef struct PgStat_FunctionEntry
466 {
467         Oid                     f_id;
468         PgStat_Counter f_numcalls;
469         PgStat_Counter f_total_time;    /* times in microseconds */
470         PgStat_Counter f_self_time;
471 } PgStat_FunctionEntry;
472
473 /* ----------
474  * PgStat_MsgFuncstat                   Sent by the backend to report function
475  *                                                              usage statistics.
476  * ----------
477  */
478 #define PGSTAT_NUM_FUNCENTRIES  \
479         ((PGSTAT_MSG_PAYLOAD - sizeof(Oid) - sizeof(int))  \
480          / sizeof(PgStat_FunctionEntry))
481
482 typedef struct PgStat_MsgFuncstat
483 {
484         PgStat_MsgHdr m_hdr;
485         Oid                     m_databaseid;
486         int                     m_nentries;
487         PgStat_FunctionEntry m_entry[PGSTAT_NUM_FUNCENTRIES];
488 } PgStat_MsgFuncstat;
489
490 /* ----------
491  * PgStat_MsgFuncpurge                  Sent by the backend to tell the collector
492  *                                                              about dead functions.
493  * ----------
494  */
495 #define PGSTAT_NUM_FUNCPURGE  \
496         ((PGSTAT_MSG_PAYLOAD - sizeof(Oid) - sizeof(int))  \
497          / sizeof(Oid))
498
499 typedef struct PgStat_MsgFuncpurge
500 {
501         PgStat_MsgHdr m_hdr;
502         Oid                     m_databaseid;
503         int                     m_nentries;
504         Oid                     m_functionid[PGSTAT_NUM_FUNCPURGE];
505 } PgStat_MsgFuncpurge;
506
507 /* ----------
508  * PgStat_MsgDeadlock                   Sent by the backend to tell the collector
509  *                                                              about a deadlock that occurred.
510  * ----------
511  */
512 typedef struct PgStat_MsgDeadlock
513 {
514         PgStat_MsgHdr m_hdr;
515         Oid                     m_databaseid;
516 } PgStat_MsgDeadlock;
517
518
519 /* ----------
520  * PgStat_Msg                                   Union over all possible messages.
521  * ----------
522  */
523 typedef union PgStat_Msg
524 {
525         PgStat_MsgHdr msg_hdr;
526         PgStat_MsgDummy msg_dummy;
527         PgStat_MsgInquiry msg_inquiry;
528         PgStat_MsgTabstat msg_tabstat;
529         PgStat_MsgTabpurge msg_tabpurge;
530         PgStat_MsgDropdb msg_dropdb;
531         PgStat_MsgResetcounter msg_resetcounter;
532         PgStat_MsgResetsharedcounter msg_resetsharedcounter;
533         PgStat_MsgResetsinglecounter msg_resetsinglecounter;
534         PgStat_MsgAutovacStart msg_autovacuum;
535         PgStat_MsgVacuum msg_vacuum;
536         PgStat_MsgAnalyze msg_analyze;
537         PgStat_MsgArchiver msg_archiver;
538         PgStat_MsgBgWriter msg_bgwriter;
539         PgStat_MsgFuncstat msg_funcstat;
540         PgStat_MsgFuncpurge msg_funcpurge;
541         PgStat_MsgRecoveryConflict msg_recoveryconflict;
542         PgStat_MsgDeadlock msg_deadlock;
543 } PgStat_Msg;
544
545
546 /* ------------------------------------------------------------
547  * Statistic collector data structures follow
548  *
549  * PGSTAT_FILE_FORMAT_ID should be changed whenever any of these
550  * data structures change.
551  * ------------------------------------------------------------
552  */
553
554 #define PGSTAT_FILE_FORMAT_ID   0x01A5BC9D
555
556 /* ----------
557  * PgStat_StatDBEntry                   The collector's data per database
558  * ----------
559  */
560 typedef struct PgStat_StatDBEntry
561 {
562         Oid                     databaseid;
563         PgStat_Counter n_xact_commit;
564         PgStat_Counter n_xact_rollback;
565         PgStat_Counter n_blocks_fetched;
566         PgStat_Counter n_blocks_hit;
567         PgStat_Counter n_tuples_returned;
568         PgStat_Counter n_tuples_fetched;
569         PgStat_Counter n_tuples_inserted;
570         PgStat_Counter n_tuples_updated;
571         PgStat_Counter n_tuples_deleted;
572         TimestampTz last_autovac_time;
573         PgStat_Counter n_conflict_tablespace;
574         PgStat_Counter n_conflict_lock;
575         PgStat_Counter n_conflict_snapshot;
576         PgStat_Counter n_conflict_bufferpin;
577         PgStat_Counter n_conflict_startup_deadlock;
578         PgStat_Counter n_temp_files;
579         PgStat_Counter n_temp_bytes;
580         PgStat_Counter n_deadlocks;
581         PgStat_Counter n_block_read_time;       /* times in microseconds */
582         PgStat_Counter n_block_write_time;
583
584         TimestampTz stat_reset_timestamp;
585         TimestampTz stats_timestamp;    /* time of db stats file update */
586
587         /*
588          * tables and functions must be last in the struct, because we don't write
589          * the pointers out to the stats file.
590          */
591         HTAB       *tables;
592         HTAB       *functions;
593 } PgStat_StatDBEntry;
594
595
596 /* ----------
597  * PgStat_StatTabEntry                  The collector's data per table (or index)
598  * ----------
599  */
600 typedef struct PgStat_StatTabEntry
601 {
602         Oid                     tableid;
603
604         PgStat_Counter numscans;
605
606         PgStat_Counter tuples_returned;
607         PgStat_Counter tuples_fetched;
608
609         PgStat_Counter tuples_inserted;
610         PgStat_Counter tuples_updated;
611         PgStat_Counter tuples_deleted;
612         PgStat_Counter tuples_hot_updated;
613
614         PgStat_Counter n_live_tuples;
615         PgStat_Counter n_dead_tuples;
616         PgStat_Counter changes_since_analyze;
617
618         PgStat_Counter blocks_fetched;
619         PgStat_Counter blocks_hit;
620
621         TimestampTz vacuum_timestamp;           /* user initiated vacuum */
622         PgStat_Counter vacuum_count;
623         TimestampTz autovac_vacuum_timestamp;           /* autovacuum initiated */
624         PgStat_Counter autovac_vacuum_count;
625         TimestampTz analyze_timestamp;          /* user initiated */
626         PgStat_Counter analyze_count;
627         TimestampTz autovac_analyze_timestamp;          /* autovacuum initiated */
628         PgStat_Counter autovac_analyze_count;
629 } PgStat_StatTabEntry;
630
631
632 /* ----------
633  * PgStat_StatFuncEntry                 The collector's data per function
634  * ----------
635  */
636 typedef struct PgStat_StatFuncEntry
637 {
638         Oid                     functionid;
639
640         PgStat_Counter f_numcalls;
641
642         PgStat_Counter f_total_time;    /* times in microseconds */
643         PgStat_Counter f_self_time;
644 } PgStat_StatFuncEntry;
645
646
647 /*
648  * Archiver statistics kept in the stats collector
649  */
650 typedef struct PgStat_ArchiverStats
651 {
652         PgStat_Counter archived_count;          /* archival successes */
653         char            last_archived_wal[MAX_XFN_CHARS + 1];   /* last WAL file
654                                                                                                                  * archived */
655         TimestampTz last_archived_timestamp;            /* last archival success time */
656         PgStat_Counter failed_count;    /* failed archival attempts */
657         char            last_failed_wal[MAX_XFN_CHARS + 1];             /* WAL file involved in
658                                                                                                                  * last failure */
659         TimestampTz last_failed_timestamp;      /* last archival failure time */
660         TimestampTz stat_reset_timestamp;
661 } PgStat_ArchiverStats;
662
663 /*
664  * Global statistics kept in the stats collector
665  */
666 typedef struct PgStat_GlobalStats
667 {
668         TimestampTz stats_timestamp;    /* time of stats file update */
669         PgStat_Counter timed_checkpoints;
670         PgStat_Counter requested_checkpoints;
671         PgStat_Counter checkpoint_write_time;           /* times in milliseconds */
672         PgStat_Counter checkpoint_sync_time;
673         PgStat_Counter buf_written_checkpoints;
674         PgStat_Counter buf_written_clean;
675         PgStat_Counter maxwritten_clean;
676         PgStat_Counter buf_written_backend;
677         PgStat_Counter buf_fsync_backend;
678         PgStat_Counter buf_alloc;
679         TimestampTz stat_reset_timestamp;
680 } PgStat_GlobalStats;
681
682
683 /* ----------
684  * Backend states
685  * ----------
686  */
687 typedef enum BackendState
688 {
689         STATE_UNDEFINED,
690         STATE_IDLE,
691         STATE_RUNNING,
692         STATE_IDLEINTRANSACTION,
693         STATE_FASTPATH,
694         STATE_IDLEINTRANSACTION_ABORTED,
695         STATE_DISABLED
696 } BackendState;
697
698 /* ----------
699  * Shared-memory data structures
700  * ----------
701  */
702
703
704 /*
705  * PgBackendSSLStatus
706  *
707  * For each backend, we keep the SSL status in a separate struct, that
708  * is only filled in if SSL is enabled.
709  */
710 typedef struct PgBackendSSLStatus
711 {
712         /* Information about SSL connection */
713         int                     ssl_bits;
714         bool            ssl_compression;
715         char            ssl_version[NAMEDATALEN];               /* MUST be null-terminated */
716         char            ssl_cipher[NAMEDATALEN];                /* MUST be null-terminated */
717         char            ssl_clientdn[NAMEDATALEN];              /* MUST be null-terminated */
718 } PgBackendSSLStatus;
719
720
721 /* ----------
722  * PgBackendStatus
723  *
724  * Each live backend maintains a PgBackendStatus struct in shared memory
725  * showing its current activity.  (The structs are allocated according to
726  * BackendId, but that is not critical.)  Note that the collector process
727  * has no involvement in, or even access to, these structs.
728  * ----------
729  */
730 typedef struct PgBackendStatus
731 {
732         /*
733          * To avoid locking overhead, we use the following protocol: a backend
734          * increments st_changecount before modifying its entry, and again after
735          * finishing a modification.  A would-be reader should note the value of
736          * st_changecount, copy the entry into private memory, then check
737          * st_changecount again.  If the value hasn't changed, and if it's even,
738          * the copy is valid; otherwise start over.  This makes updates cheap
739          * while reads are potentially expensive, but that's the tradeoff we want.
740          *
741          * The above protocol needs the memory barriers to ensure that the
742          * apparent order of execution is as it desires. Otherwise, for example,
743          * the CPU might rearrange the code so that st_changecount is incremented
744          * twice before the modification on a machine with weak memory ordering.
745          * This surprising result can lead to bugs.
746          */
747         int                     st_changecount;
748
749         /* The entry is valid iff st_procpid > 0, unused if st_procpid == 0 */
750         int                     st_procpid;
751
752         /* Times when current backend, transaction, and activity started */
753         TimestampTz st_proc_start_timestamp;
754         TimestampTz st_xact_start_timestamp;
755         TimestampTz st_activity_start_timestamp;
756         TimestampTz st_state_start_timestamp;
757
758         /* Database OID, owning user's OID, connection client address */
759         Oid                     st_databaseid;
760         Oid                     st_userid;
761         SockAddr        st_clientaddr;
762         char       *st_clienthostname;          /* MUST be null-terminated */
763
764         /* Information about SSL connection */
765         bool            st_ssl;
766         PgBackendSSLStatus *st_sslstatus;
767
768         /* Is backend currently waiting on an lmgr lock? */
769         bool            st_waiting;
770
771         /* current state */
772         BackendState st_state;
773
774         /* application name; MUST be null-terminated */
775         char       *st_appname;
776
777         /* current command string; MUST be null-terminated */
778         char       *st_activity;
779 } PgBackendStatus;
780
781 /*
782  * Macros to load and store st_changecount with the memory barriers.
783  *
784  * pgstat_increment_changecount_before() and
785  * pgstat_increment_changecount_after() need to be called before and after
786  * PgBackendStatus entries are modified, respectively. This makes sure that
787  * st_changecount is incremented around the modification.
788  *
789  * Also pgstat_save_changecount_before() and pgstat_save_changecount_after()
790  * need to be called before and after PgBackendStatus entries are copied into
791  * private memory, respectively.
792  */
793 #define pgstat_increment_changecount_before(beentry)    \
794         do {    \
795                 beentry->st_changecount++;      \
796                 pg_write_barrier(); \
797         } while (0)
798
799 #define pgstat_increment_changecount_after(beentry) \
800         do {    \
801                 pg_write_barrier(); \
802                 beentry->st_changecount++;      \
803                 Assert((beentry->st_changecount & 1) == 0); \
804         } while (0)
805
806 #define pgstat_save_changecount_before(beentry, save_changecount)       \
807         do {    \
808                 save_changecount = beentry->st_changecount; \
809                 pg_read_barrier();      \
810         } while (0)
811
812 #define pgstat_save_changecount_after(beentry, save_changecount)        \
813         do {    \
814                 pg_read_barrier();      \
815                 save_changecount = beentry->st_changecount; \
816         } while (0)
817
818 /* ----------
819  * LocalPgBackendStatus
820  *
821  * When we build the backend status array, we use LocalPgBackendStatus to be
822  * able to add new values to the struct when needed without adding new fields
823  * to the shared memory. It contains the backend status as a first member.
824  * ----------
825  */
826 typedef struct LocalPgBackendStatus
827 {
828         /*
829          * Local version of the backend status entry.
830          */
831         PgBackendStatus backendStatus;
832
833         /*
834          * The xid of the current transaction if available, InvalidTransactionId
835          * if not.
836          */
837         TransactionId backend_xid;
838
839         /*
840          * The xmin of the current session if available, InvalidTransactionId if
841          * not.
842          */
843         TransactionId backend_xmin;
844 } LocalPgBackendStatus;
845
846 /*
847  * Working state needed to accumulate per-function-call timing statistics.
848  */
849 typedef struct PgStat_FunctionCallUsage
850 {
851         /* Link to function's hashtable entry (must still be there at exit!) */
852         /* NULL means we are not tracking the current function call */
853         PgStat_FunctionCounts *fs;
854         /* Total time previously charged to function, as of function start */
855         instr_time      save_f_total_time;
856         /* Backend-wide total time as of function start */
857         instr_time      save_total;
858         /* system clock as of function start */
859         instr_time      f_start;
860 } PgStat_FunctionCallUsage;
861
862
863 /* ----------
864  * GUC parameters
865  * ----------
866  */
867 extern bool pgstat_track_activities;
868 extern bool pgstat_track_counts;
869 extern int      pgstat_track_functions;
870 extern PGDLLIMPORT int pgstat_track_activity_query_size;
871 extern char *pgstat_stat_directory;
872 extern char *pgstat_stat_tmpname;
873 extern char *pgstat_stat_filename;
874
875 /*
876  * BgWriter statistics counters are updated directly by bgwriter and bufmgr
877  */
878 extern PgStat_MsgBgWriter BgWriterStats;
879
880 /*
881  * Updated by pgstat_count_buffer_*_time macros
882  */
883 extern PgStat_Counter pgStatBlockReadTime;
884 extern PgStat_Counter pgStatBlockWriteTime;
885
886 /* ----------
887  * Functions called from postmaster
888  * ----------
889  */
890 extern Size BackendStatusShmemSize(void);
891 extern void CreateSharedBackendStatus(void);
892
893 extern void pgstat_init(void);
894 extern int      pgstat_start(void);
895 extern void pgstat_reset_all(void);
896 extern void allow_immediate_pgstat_restart(void);
897
898 #ifdef EXEC_BACKEND
899 extern void PgstatCollectorMain(int argc, char *argv[]) pg_attribute_noreturn();
900 #endif
901
902
903 /* ----------
904  * Functions called from backends
905  * ----------
906  */
907 extern void pgstat_ping(void);
908
909 extern void pgstat_report_stat(bool force);
910 extern void pgstat_vacuum_stat(void);
911 extern void pgstat_drop_database(Oid databaseid);
912
913 extern void pgstat_clear_snapshot(void);
914 extern void pgstat_reset_counters(void);
915 extern void pgstat_reset_shared_counters(const char *);
916 extern void pgstat_reset_single_counter(Oid objectid, PgStat_Single_Reset_Type type);
917
918 extern void pgstat_report_autovac(Oid dboid);
919 extern void pgstat_report_vacuum(Oid tableoid, bool shared,
920                                          PgStat_Counter livetuples, PgStat_Counter deadtuples);
921 extern void pgstat_report_analyze(Relation rel,
922                                           PgStat_Counter livetuples, PgStat_Counter deadtuples);
923
924 extern void pgstat_report_recovery_conflict(int reason);
925 extern void pgstat_report_deadlock(void);
926
927 extern void pgstat_initialize(void);
928 extern void pgstat_bestart(void);
929
930 extern void pgstat_report_activity(BackendState state, const char *cmd_str);
931 extern void pgstat_report_tempfile(size_t filesize);
932 extern void pgstat_report_appname(const char *appname);
933 extern void pgstat_report_xact_timestamp(TimestampTz tstamp);
934 extern void pgstat_report_waiting(bool waiting);
935 extern const char *pgstat_get_backend_current_activity(int pid, bool checkUser);
936 extern const char *pgstat_get_crashed_backend_activity(int pid, char *buffer,
937                                                                         int buflen);
938
939 extern PgStat_TableStatus *find_tabstat_entry(Oid rel_id);
940 extern PgStat_BackendFunctionEntry *find_funcstat_entry(Oid func_id);
941
942 extern void pgstat_initstats(Relation rel);
943
944 /* nontransactional event counts are simple enough to inline */
945
946 #define pgstat_count_heap_scan(rel)                                                                     \
947         do {                                                                                                                    \
948                 if ((rel)->pgstat_info != NULL)                                                         \
949                         (rel)->pgstat_info->t_counts.t_numscans++;                              \
950         } while (0)
951 #define pgstat_count_heap_getnext(rel)                                                          \
952         do {                                                                                                                    \
953                 if ((rel)->pgstat_info != NULL)                                                         \
954                         (rel)->pgstat_info->t_counts.t_tuples_returned++;               \
955         } while (0)
956 #define pgstat_count_heap_fetch(rel)                                                            \
957         do {                                                                                                                    \
958                 if ((rel)->pgstat_info != NULL)                                                         \
959                         (rel)->pgstat_info->t_counts.t_tuples_fetched++;                \
960         } while (0)
961 #define pgstat_count_index_scan(rel)                                                            \
962         do {                                                                                                                    \
963                 if ((rel)->pgstat_info != NULL)                                                         \
964                         (rel)->pgstat_info->t_counts.t_numscans++;                              \
965         } while (0)
966 #define pgstat_count_index_tuples(rel, n)                                                       \
967         do {                                                                                                                    \
968                 if ((rel)->pgstat_info != NULL)                                                         \
969                         (rel)->pgstat_info->t_counts.t_tuples_returned += (n);  \
970         } while (0)
971 #define pgstat_count_buffer_read(rel)                                                           \
972         do {                                                                                                                    \
973                 if ((rel)->pgstat_info != NULL)                                                         \
974                         (rel)->pgstat_info->t_counts.t_blocks_fetched++;                \
975         } while (0)
976 #define pgstat_count_buffer_hit(rel)                                                            \
977         do {                                                                                                                    \
978                 if ((rel)->pgstat_info != NULL)                                                         \
979                         (rel)->pgstat_info->t_counts.t_blocks_hit++;                    \
980         } while (0)
981 #define pgstat_count_buffer_read_time(n)                                                        \
982         (pgStatBlockReadTime += (n))
983 #define pgstat_count_buffer_write_time(n)                                                       \
984         (pgStatBlockWriteTime += (n))
985
986 extern void pgstat_count_heap_insert(Relation rel, int n);
987 extern void pgstat_count_heap_update(Relation rel, bool hot);
988 extern void pgstat_count_heap_delete(Relation rel);
989 extern void pgstat_count_truncate(Relation rel);
990 extern void pgstat_update_heap_dead_tuples(Relation rel, int delta);
991
992 extern void pgstat_init_function_usage(FunctionCallInfoData *fcinfo,
993                                                    PgStat_FunctionCallUsage *fcu);
994 extern void pgstat_end_function_usage(PgStat_FunctionCallUsage *fcu,
995                                                   bool finalize);
996
997 extern void AtEOXact_PgStat(bool isCommit);
998 extern void AtEOSubXact_PgStat(bool isCommit, int nestDepth);
999
1000 extern void AtPrepare_PgStat(void);
1001 extern void PostPrepare_PgStat(void);
1002
1003 extern void pgstat_twophase_postcommit(TransactionId xid, uint16 info,
1004                                                    void *recdata, uint32 len);
1005 extern void pgstat_twophase_postabort(TransactionId xid, uint16 info,
1006                                                   void *recdata, uint32 len);
1007
1008 extern void pgstat_send_archiver(const char *xlog, bool failed);
1009 extern void pgstat_send_bgwriter(void);
1010
1011 /* ----------
1012  * Support functions for the SQL-callable functions to
1013  * generate the pgstat* views.
1014  * ----------
1015  */
1016 extern PgStat_StatDBEntry *pgstat_fetch_stat_dbentry(Oid dbid);
1017 extern PgStat_StatTabEntry *pgstat_fetch_stat_tabentry(Oid relid);
1018 extern PgBackendStatus *pgstat_fetch_stat_beentry(int beid);
1019 extern LocalPgBackendStatus *pgstat_fetch_stat_local_beentry(int beid);
1020 extern PgStat_StatFuncEntry *pgstat_fetch_stat_funcentry(Oid funcid);
1021 extern int      pgstat_fetch_stat_numbackends(void);
1022 extern PgStat_ArchiverStats *pgstat_fetch_stat_archiver(void);
1023 extern PgStat_GlobalStats *pgstat_fetch_global(void);
1024
1025 #endif   /* PGSTAT_H */