Age Owner Branch data TLA Line data Source code
1 : : /* ----------
2 : : * pgstat_internal.h
3 : : *
4 : : * Definitions for the PostgreSQL cumulative statistics system that should
5 : : * only be needed by files implementing statistics support (rather than ones
6 : : * reporting / querying stats).
7 : : *
8 : : * Copyright (c) 2001-2024, PostgreSQL Global Development Group
9 : : *
10 : : * src/include/utils/pgstat_internal.h
11 : : * ----------
12 : : */
13 : : #ifndef PGSTAT_INTERNAL_H
14 : : #define PGSTAT_INTERNAL_H
15 : :
16 : :
17 : : #include "common/hashfn_unstable.h"
18 : : #include "lib/dshash.h"
19 : : #include "lib/ilist.h"
20 : : #include "pgstat.h"
21 : : #include "storage/lwlock.h"
22 : : #include "utils/dsa.h"
23 : :
24 : :
25 : : /*
26 : : * Types related to shared memory storage of statistics.
27 : : *
28 : : * Per-object statistics are stored in the "shared stats" hashtable. That
29 : : * table's entries (PgStatShared_HashEntry) contain a pointer to the actual stats
30 : : * data for the object (the size of the stats data varies depending on the
31 : : * kind of stats). The table is keyed by PgStat_HashKey.
32 : : *
33 : : * Once a backend has a reference to a shared stats entry, it increments the
34 : : * entry's refcount. Even after stats data is dropped (e.g., due to a DROP
35 : : * TABLE), the entry itself can only be deleted once all references have been
36 : : * released.
37 : : *
38 : : * These refcounts, in combination with a backend local hashtable
39 : : * (pgStatEntryRefHash, with entries pointing to PgStat_EntryRef) in front of
40 : : * the shared hash table, mean that most stats work can happen without
41 : : * touching the shared hash table, reducing contention.
42 : : *
43 : : * Once there are pending stats updates for a table PgStat_EntryRef->pending
44 : : * is allocated to contain a working space for as-of-yet-unapplied stats
45 : : * updates. Once the stats are flushed, PgStat_EntryRef->pending is freed.
46 : : *
47 : : * Each stat kind in the shared hash table has a fixed member
48 : : * PgStatShared_Common as the first element.
49 : : */
50 : :
51 : : /* struct for shared statistics hash entry key. */
52 : : typedef struct PgStat_HashKey
53 : : {
54 : : PgStat_Kind kind; /* statistics entry kind */
55 : : Oid dboid; /* database ID. InvalidOid for shared objects. */
56 : : Oid objoid; /* object ID, either table or function. */
57 : : } PgStat_HashKey;
58 : :
59 : : /*
60 : : * Shared statistics hash entry. Doesn't itself contain any stats, but points
61 : : * to them (with ->body). That allows the stats entries themselves to be of
62 : : * variable size.
63 : : */
64 : : typedef struct PgStatShared_HashEntry
65 : : {
66 : : PgStat_HashKey key; /* hash key */
67 : :
68 : : /*
69 : : * If dropped is set, backends need to release their references so that
70 : : * the memory for the entry can be freed. No new references may be made
71 : : * once marked as dropped.
72 : : */
73 : : bool dropped;
74 : :
75 : : /*
76 : : * Refcount managing lifetime of the entry itself (as opposed to the
77 : : * dshash entry pointing to it). The stats lifetime has to be separate
78 : : * from the hash table entry lifetime because we allow backends to point
79 : : * to a stats entry without holding a hash table lock (and some other
80 : : * reasons).
81 : : *
82 : : * As long as the entry is not dropped, 1 is added to the refcount
83 : : * representing that the entry should not be dropped. In addition each
84 : : * backend that has a reference to the entry needs to increment the
85 : : * refcount as long as it does.
86 : : *
87 : : * May only be incremented / decremented while holding at least a shared
88 : : * lock on the dshash partition containing the entry. It needs to be an
89 : : * atomic variable because multiple backends can increment the refcount
90 : : * with just a shared lock.
91 : : *
92 : : * When the refcount reaches 0 the entry needs to be freed.
93 : : */
94 : : pg_atomic_uint32 refcount;
95 : :
96 : : /*
97 : : * Pointer to shared stats. The stats entry always starts with
98 : : * PgStatShared_Common, embedded in a larger struct containing the
99 : : * PgStat_Kind specific stats fields.
100 : : */
101 : : dsa_pointer body;
102 : : } PgStatShared_HashEntry;
103 : :
104 : : /*
105 : : * Common header struct for PgStatShared_*.
106 : : */
107 : : typedef struct PgStatShared_Common
108 : : {
109 : : uint32 magic; /* just a validity cross-check */
110 : : /* lock protecting stats contents (i.e. data following the header) */
111 : : LWLock lock;
112 : : } PgStatShared_Common;
113 : :
114 : : /*
115 : : * A backend local reference to a shared stats entry. As long as at least one
116 : : * such reference exists, the shared stats entry will not be released.
117 : : *
118 : : * If there are pending stats update to the shared stats, these are stored in
119 : : * ->pending.
120 : : */
121 : : typedef struct PgStat_EntryRef
122 : : {
123 : : /*
124 : : * Pointer to the PgStatShared_HashEntry entry in the shared stats
125 : : * hashtable.
126 : : */
127 : : PgStatShared_HashEntry *shared_entry;
128 : :
129 : : /*
130 : : * Pointer to the stats data (i.e. PgStatShared_HashEntry->body), resolved
131 : : * as a local pointer, to avoid repeated dsa_get_address() calls.
132 : : */
133 : : PgStatShared_Common *shared_stats;
134 : :
135 : : /*
136 : : * Pending statistics data that will need to be flushed to shared memory
137 : : * stats eventually. Each stats kind utilizing pending data defines what
138 : : * format its pending data has and needs to provide a
139 : : * PgStat_KindInfo->flush_pending_cb callback to merge pending into shared
140 : : * stats.
141 : : */
142 : : void *pending;
143 : : dlist_node pending_node; /* membership in pgStatPending list */
144 : : } PgStat_EntryRef;
145 : :
146 : :
147 : : /*
148 : : * Some stats changes are transactional. To maintain those, a stack of
149 : : * PgStat_SubXactStatus entries is maintained, which contain data pertaining
150 : : * to the current transaction and its active subtransactions.
151 : : */
152 : : typedef struct PgStat_SubXactStatus
153 : : {
154 : : int nest_level; /* subtransaction nest level */
155 : :
156 : : struct PgStat_SubXactStatus *prev; /* higher-level subxact if any */
157 : :
158 : : /*
159 : : * Statistics for transactionally dropped objects need to be
160 : : * transactionally dropped as well. Collect the stats dropped in the
161 : : * current (sub-)transaction and only execute the stats drop when we know
162 : : * if the transaction commits/aborts. To handle replicas and crashes,
163 : : * stats drops are included in commit / abort records.
164 : : */
165 : : dclist_head pending_drops;
166 : :
167 : : /*
168 : : * Tuple insertion/deletion counts for an open transaction can't be
169 : : * propagated into PgStat_TableStatus counters until we know if it is
170 : : * going to commit or abort. Hence, we keep these counts in per-subxact
171 : : * structs that live in TopTransactionContext. This data structure is
172 : : * designed on the assumption that subxacts won't usually modify very many
173 : : * tables.
174 : : */
175 : : PgStat_TableXactStatus *first; /* head of list for this subxact */
176 : : } PgStat_SubXactStatus;
177 : :
178 : :
179 : : /*
180 : : * Metadata for a specific kind of statistics.
181 : : */
182 : : typedef struct PgStat_KindInfo
183 : : {
184 : : /*
185 : : * Do a fixed number of stats objects exist for this kind of stats (e.g.
186 : : * bgwriter stats) or not (e.g. tables).
187 : : */
188 : : bool fixed_amount:1;
189 : :
190 : : /*
191 : : * Can stats of this kind be accessed from another database? Determines
192 : : * whether a stats object gets included in stats snapshots.
193 : : */
194 : : bool accessed_across_databases:1;
195 : :
196 : : /*
197 : : * For variable-numbered stats: Identified on-disk using a name, rather
198 : : * than PgStat_HashKey. Probably only needed for replication slot stats.
199 : : */
200 : : bool named_on_disk:1;
201 : :
202 : : /*
203 : : * The size of an entry in the shared stats hash table (pointed to by
204 : : * PgStatShared_HashEntry->body).
205 : : */
206 : : uint32 shared_size;
207 : :
208 : : /*
209 : : * The offset/size of statistics inside the shared stats entry. Used when
210 : : * [de-]serializing statistics to / from disk respectively. Separate from
211 : : * shared_size because [de-]serialization may not include in-memory state
212 : : * like lwlocks.
213 : : */
214 : : uint32 shared_data_off;
215 : : uint32 shared_data_len;
216 : :
217 : : /*
218 : : * The size of the pending data for this kind. E.g. how large
219 : : * PgStat_EntryRef->pending is. Used for allocations.
220 : : *
221 : : * 0 signals that an entry of this kind should never have a pending entry.
222 : : */
223 : : uint32 pending_size;
224 : :
225 : : /*
226 : : * For variable-numbered stats: flush pending stats. Required if pending
227 : : * data is used.
228 : : */
229 : : bool (*flush_pending_cb) (PgStat_EntryRef *sr, bool nowait);
230 : :
231 : : /*
232 : : * For variable-numbered stats: delete pending stats. Optional.
233 : : */
234 : : void (*delete_pending_cb) (PgStat_EntryRef *sr);
235 : :
236 : : /*
237 : : * For variable-numbered stats: reset the reset timestamp. Optional.
238 : : */
239 : : void (*reset_timestamp_cb) (PgStatShared_Common *header, TimestampTz ts);
240 : :
241 : : /*
242 : : * For variable-numbered stats with named_on_disk. Optional.
243 : : */
244 : : void (*to_serialized_name) (const PgStat_HashKey *key,
245 : : const PgStatShared_Common *header, NameData *name);
246 : : bool (*from_serialized_name) (const NameData *name, PgStat_HashKey *key);
247 : :
248 : : /*
249 : : * For fixed-numbered statistics: Reset All.
250 : : */
251 : : void (*reset_all_cb) (TimestampTz ts);
252 : :
253 : : /*
254 : : * For fixed-numbered statistics: Build snapshot for entry
255 : : */
256 : : void (*snapshot_cb) (void);
257 : :
258 : : /* name of the kind of stats */
259 : : const char *const name;
260 : : } PgStat_KindInfo;
261 : :
262 : :
263 : : /*
264 : : * List of SLRU names that we keep stats for. There is no central registry of
265 : : * SLRUs, so we use this fixed list instead. The "other" entry is used for
266 : : * all SLRUs without an explicit entry (e.g. SLRUs in extensions).
267 : : *
268 : : * This is only defined here so that SLRU_NUM_ELEMENTS is known for later type
269 : : * definitions.
270 : : */
271 : : static const char *const slru_names[] = {
272 : : "commit_timestamp",
273 : : "multixact_member",
274 : : "multixact_offset",
275 : : "notify",
276 : : "serializable",
277 : : "subtransaction",
278 : : "transaction",
279 : : "other" /* has to be last */
280 : : };
281 : :
282 : : #define SLRU_NUM_ELEMENTS lengthof(slru_names)
283 : :
284 : :
285 : : /* ----------
286 : : * Types and definitions for different kinds of fixed-amount stats.
287 : : *
288 : : * Single-writer stats use the changecount mechanism to achieve low-overhead
289 : : * writes - they're obviously more performance critical than reads. Check the
290 : : * definition of struct PgBackendStatus for some explanation of the
291 : : * changecount mechanism.
292 : : *
293 : : * Because the obvious implementation of resetting single-writer stats isn't
294 : : * compatible with that (another backend needs to write), we don't scribble on
295 : : * shared stats while resetting. Instead, just record the current counter
296 : : * values in a copy of the stats data, which is protected by ->lock. See
297 : : * pgstat_fetch_stat_(archiver|bgwriter|checkpointer) for the reader side.
298 : : *
299 : : * The only exception to that is the stat_reset_timestamp in these structs,
300 : : * which is protected by ->lock, because it has to be written by another
301 : : * backend while resetting.
302 : : * ----------
303 : : */
304 : :
305 : : typedef struct PgStatShared_Archiver
306 : : {
307 : : /* lock protects ->reset_offset as well as stats->stat_reset_timestamp */
308 : : LWLock lock;
309 : : uint32 changecount;
310 : : PgStat_ArchiverStats stats;
311 : : PgStat_ArchiverStats reset_offset;
312 : : } PgStatShared_Archiver;
313 : :
314 : : typedef struct PgStatShared_BgWriter
315 : : {
316 : : /* lock protects ->reset_offset as well as stats->stat_reset_timestamp */
317 : : LWLock lock;
318 : : uint32 changecount;
319 : : PgStat_BgWriterStats stats;
320 : : PgStat_BgWriterStats reset_offset;
321 : : } PgStatShared_BgWriter;
322 : :
323 : : typedef struct PgStatShared_Checkpointer
324 : : {
325 : : /* lock protects ->reset_offset as well as stats->stat_reset_timestamp */
326 : : LWLock lock;
327 : : uint32 changecount;
328 : : PgStat_CheckpointerStats stats;
329 : : PgStat_CheckpointerStats reset_offset;
330 : : } PgStatShared_Checkpointer;
331 : :
332 : : /* Shared-memory ready PgStat_IO */
333 : : typedef struct PgStatShared_IO
334 : : {
335 : : /*
336 : : * locks[i] protects stats.stats[i]. locks[0] also protects
337 : : * stats.stat_reset_timestamp.
338 : : */
339 : : LWLock locks[BACKEND_NUM_TYPES];
340 : : PgStat_IO stats;
341 : : } PgStatShared_IO;
342 : :
343 : : typedef struct PgStatShared_SLRU
344 : : {
345 : : /* lock protects ->stats */
346 : : LWLock lock;
347 : : PgStat_SLRUStats stats[SLRU_NUM_ELEMENTS];
348 : : } PgStatShared_SLRU;
349 : :
350 : : typedef struct PgStatShared_Wal
351 : : {
352 : : /* lock protects ->stats */
353 : : LWLock lock;
354 : : PgStat_WalStats stats;
355 : : } PgStatShared_Wal;
356 : :
357 : :
358 : :
359 : : /* ----------
360 : : * Types and definitions for different kinds of variable-amount stats.
361 : : *
362 : : * Each struct has to start with PgStatShared_Common, containing information
363 : : * common across the different types of stats. Kind-specific data follows.
364 : : * ----------
365 : : */
366 : :
367 : : typedef struct PgStatShared_Database
368 : : {
369 : : PgStatShared_Common header;
370 : : PgStat_StatDBEntry stats;
371 : : } PgStatShared_Database;
372 : :
373 : : typedef struct PgStatShared_Relation
374 : : {
375 : : PgStatShared_Common header;
376 : : PgStat_StatTabEntry stats;
377 : : } PgStatShared_Relation;
378 : :
379 : : typedef struct PgStatShared_Function
380 : : {
381 : : PgStatShared_Common header;
382 : : PgStat_StatFuncEntry stats;
383 : : } PgStatShared_Function;
384 : :
385 : : typedef struct PgStatShared_Subscription
386 : : {
387 : : PgStatShared_Common header;
388 : : PgStat_StatSubEntry stats;
389 : : } PgStatShared_Subscription;
390 : :
391 : : typedef struct PgStatShared_ReplSlot
392 : : {
393 : : PgStatShared_Common header;
394 : : PgStat_StatReplSlotEntry stats;
395 : : } PgStatShared_ReplSlot;
396 : :
397 : :
398 : : /*
399 : : * Central shared memory entry for the cumulative stats system.
400 : : *
401 : : * Fixed amount stats, the dynamic shared memory hash table for
402 : : * non-fixed-amount stats, as well as remaining bits and pieces are all
403 : : * reached from here.
404 : : */
405 : : typedef struct PgStat_ShmemControl
406 : : {
407 : : void *raw_dsa_area;
408 : :
409 : : /*
410 : : * Stats for variable-numbered objects are kept in this shared hash table.
411 : : * See comment above PgStat_Kind for details.
412 : : */
413 : : dshash_table_handle hash_handle; /* shared dbstat hash */
414 : :
415 : : /* Has the stats system already been shut down? Just a debugging check. */
416 : : bool is_shutdown;
417 : :
418 : : /*
419 : : * Whenever statistics for dropped objects could not be freed - because
420 : : * backends still have references - the dropping backend calls
421 : : * pgstat_request_entry_refs_gc() incrementing this counter. Eventually
422 : : * that causes backends to run pgstat_gc_entry_refs(), allowing memory to
423 : : * be reclaimed.
424 : : */
425 : : pg_atomic_uint64 gc_request_count;
426 : :
427 : : /*
428 : : * Stats data for fixed-numbered objects.
429 : : */
430 : : PgStatShared_Archiver archiver;
431 : : PgStatShared_BgWriter bgwriter;
432 : : PgStatShared_Checkpointer checkpointer;
433 : : PgStatShared_IO io;
434 : : PgStatShared_SLRU slru;
435 : : PgStatShared_Wal wal;
436 : : } PgStat_ShmemControl;
437 : :
438 : :
439 : : /*
440 : : * Cached statistics snapshot
441 : : */
442 : : typedef struct PgStat_Snapshot
443 : : {
444 : : PgStat_FetchConsistency mode;
445 : :
446 : : /* time at which snapshot was taken */
447 : : TimestampTz snapshot_timestamp;
448 : :
449 : : bool fixed_valid[PGSTAT_NUM_KINDS];
450 : :
451 : : PgStat_ArchiverStats archiver;
452 : :
453 : : PgStat_BgWriterStats bgwriter;
454 : :
455 : : PgStat_CheckpointerStats checkpointer;
456 : :
457 : : PgStat_IO io;
458 : :
459 : : PgStat_SLRUStats slru[SLRU_NUM_ELEMENTS];
460 : :
461 : : PgStat_WalStats wal;
462 : :
463 : : /* to free snapshot in bulk */
464 : : MemoryContext context;
465 : : struct pgstat_snapshot_hash *stats;
466 : : } PgStat_Snapshot;
467 : :
468 : :
469 : : /*
470 : : * Collection of backend-local stats state.
471 : : */
472 : : typedef struct PgStat_LocalState
473 : : {
474 : : PgStat_ShmemControl *shmem;
475 : : dsa_area *dsa;
476 : : dshash_table *shared_hash;
477 : :
478 : : /* the current statistics snapshot */
479 : : PgStat_Snapshot snapshot;
480 : : } PgStat_LocalState;
481 : :
482 : :
483 : : /*
484 : : * Inline functions defined further below.
485 : : */
486 : :
487 : : static inline void pgstat_begin_changecount_write(uint32 *cc);
488 : : static inline void pgstat_end_changecount_write(uint32 *cc);
489 : : static inline uint32 pgstat_begin_changecount_read(uint32 *cc);
490 : : static inline bool pgstat_end_changecount_read(uint32 *cc, uint32 cc_before);
491 : :
492 : : static inline void pgstat_copy_changecounted_stats(void *dst, void *src, size_t len,
493 : : uint32 *cc);
494 : :
495 : : static inline int pgstat_cmp_hash_key(const void *a, const void *b, size_t size, void *arg);
496 : : static inline uint32 pgstat_hash_hash_key(const void *d, size_t size, void *arg);
497 : : static inline size_t pgstat_get_entry_len(PgStat_Kind kind);
498 : : static inline void *pgstat_get_entry_data(PgStat_Kind kind, PgStatShared_Common *entry);
499 : :
500 : :
501 : : /*
502 : : * Functions in pgstat.c
503 : : */
504 : :
505 : : extern const PgStat_KindInfo *pgstat_get_kind_info(PgStat_Kind kind);
506 : :
507 : : #ifdef USE_ASSERT_CHECKING
508 : : extern void pgstat_assert_is_up(void);
509 : : #else
510 : : #define pgstat_assert_is_up() ((void)true)
511 : : #endif
512 : :
513 : : extern void pgstat_delete_pending_entry(PgStat_EntryRef *entry_ref);
514 : : extern PgStat_EntryRef *pgstat_prep_pending_entry(PgStat_Kind kind, Oid dboid, Oid objoid, bool *created_entry);
515 : : extern PgStat_EntryRef *pgstat_fetch_pending_entry(PgStat_Kind kind, Oid dboid, Oid objoid);
516 : :
517 : : extern void *pgstat_fetch_entry(PgStat_Kind kind, Oid dboid, Oid objoid);
518 : : extern void pgstat_snapshot_fixed(PgStat_Kind kind);
519 : :
520 : :
521 : : /*
522 : : * Functions in pgstat_archiver.c
523 : : */
524 : :
525 : : extern void pgstat_archiver_reset_all_cb(TimestampTz ts);
526 : : extern void pgstat_archiver_snapshot_cb(void);
527 : :
528 : :
529 : : /*
530 : : * Functions in pgstat_bgwriter.c
531 : : */
532 : :
533 : : extern void pgstat_bgwriter_reset_all_cb(TimestampTz ts);
534 : : extern void pgstat_bgwriter_snapshot_cb(void);
535 : :
536 : :
537 : : /*
538 : : * Functions in pgstat_checkpointer.c
539 : : */
540 : :
541 : : extern void pgstat_checkpointer_reset_all_cb(TimestampTz ts);
542 : : extern void pgstat_checkpointer_snapshot_cb(void);
543 : :
544 : :
545 : : /*
546 : : * Functions in pgstat_database.c
547 : : */
548 : :
549 : : extern void pgstat_report_disconnect(Oid dboid);
550 : : extern void pgstat_update_dbstats(TimestampTz ts);
551 : : extern void AtEOXact_PgStat_Database(bool isCommit, bool parallel);
552 : :
553 : : extern PgStat_StatDBEntry *pgstat_prep_database_pending(Oid dboid);
554 : : extern void pgstat_reset_database_timestamp(Oid dboid, TimestampTz ts);
555 : : extern bool pgstat_database_flush_cb(PgStat_EntryRef *entry_ref, bool nowait);
556 : : extern void pgstat_database_reset_timestamp_cb(PgStatShared_Common *header, TimestampTz ts);
557 : :
558 : :
559 : : /*
560 : : * Functions in pgstat_function.c
561 : : */
562 : :
563 : : extern bool pgstat_function_flush_cb(PgStat_EntryRef *entry_ref, bool nowait);
564 : :
565 : :
566 : : /*
567 : : * Functions in pgstat_io.c
568 : : */
569 : :
570 : : extern bool pgstat_flush_io(bool nowait);
571 : : extern void pgstat_io_reset_all_cb(TimestampTz ts);
572 : : extern void pgstat_io_snapshot_cb(void);
573 : :
574 : :
575 : : /*
576 : : * Functions in pgstat_relation.c
577 : : */
578 : :
579 : : extern void AtEOXact_PgStat_Relations(PgStat_SubXactStatus *xact_state, bool isCommit);
580 : : extern void AtEOSubXact_PgStat_Relations(PgStat_SubXactStatus *xact_state, bool isCommit, int nestDepth);
581 : : extern void AtPrepare_PgStat_Relations(PgStat_SubXactStatus *xact_state);
582 : : extern void PostPrepare_PgStat_Relations(PgStat_SubXactStatus *xact_state);
583 : :
584 : : extern bool pgstat_relation_flush_cb(PgStat_EntryRef *entry_ref, bool nowait);
585 : : extern void pgstat_relation_delete_pending_cb(PgStat_EntryRef *entry_ref);
586 : :
587 : :
588 : : /*
589 : : * Functions in pgstat_replslot.c
590 : : */
591 : :
592 : : extern void pgstat_replslot_reset_timestamp_cb(PgStatShared_Common *header, TimestampTz ts);
593 : : extern void pgstat_replslot_to_serialized_name_cb(const PgStat_HashKey *key, const PgStatShared_Common *header, NameData *name);
594 : : extern bool pgstat_replslot_from_serialized_name_cb(const NameData *name, PgStat_HashKey *key);
595 : :
596 : :
597 : : /*
598 : : * Functions in pgstat_shmem.c
599 : : */
600 : :
601 : : extern void pgstat_attach_shmem(void);
602 : : extern void pgstat_detach_shmem(void);
603 : :
604 : : extern PgStat_EntryRef *pgstat_get_entry_ref(PgStat_Kind kind, Oid dboid, Oid objoid,
605 : : bool create, bool *created_entry);
606 : : extern bool pgstat_lock_entry(PgStat_EntryRef *entry_ref, bool nowait);
607 : : extern bool pgstat_lock_entry_shared(PgStat_EntryRef *entry_ref, bool nowait);
608 : : extern void pgstat_unlock_entry(PgStat_EntryRef *entry_ref);
609 : : extern bool pgstat_drop_entry(PgStat_Kind kind, Oid dboid, Oid objoid);
610 : : extern void pgstat_drop_all_entries(void);
611 : : extern PgStat_EntryRef *pgstat_get_entry_ref_locked(PgStat_Kind kind, Oid dboid, Oid objoid,
612 : : bool nowait);
613 : : extern void pgstat_reset_entry(PgStat_Kind kind, Oid dboid, Oid objoid, TimestampTz ts);
614 : : extern void pgstat_reset_entries_of_kind(PgStat_Kind kind, TimestampTz ts);
615 : : extern void pgstat_reset_matching_entries(bool (*do_reset) (PgStatShared_HashEntry *, Datum),
616 : : Datum match_data,
617 : : TimestampTz ts);
618 : :
619 : : extern void pgstat_request_entry_refs_gc(void);
620 : : extern PgStatShared_Common *pgstat_init_entry(PgStat_Kind kind,
621 : : PgStatShared_HashEntry *shhashent);
622 : :
623 : :
624 : : /*
625 : : * Functions in pgstat_slru.c
626 : : */
627 : :
628 : : extern bool pgstat_slru_flush(bool nowait);
629 : : extern void pgstat_slru_reset_all_cb(TimestampTz ts);
630 : : extern void pgstat_slru_snapshot_cb(void);
631 : :
632 : :
633 : : /*
634 : : * Functions in pgstat_wal.c
635 : : */
636 : :
637 : : extern bool pgstat_flush_wal(bool nowait);
638 : : extern void pgstat_init_wal(void);
639 : : extern bool pgstat_have_pending_wal(void);
640 : :
641 : : extern void pgstat_wal_reset_all_cb(TimestampTz ts);
642 : : extern void pgstat_wal_snapshot_cb(void);
643 : :
644 : :
645 : : /*
646 : : * Functions in pgstat_subscription.c
647 : : */
648 : :
649 : : extern bool pgstat_subscription_flush_cb(PgStat_EntryRef *entry_ref, bool nowait);
650 : : extern void pgstat_subscription_reset_timestamp_cb(PgStatShared_Common *header, TimestampTz ts);
651 : :
652 : :
653 : : /*
654 : : * Functions in pgstat_xact.c
655 : : */
656 : :
657 : : extern PgStat_SubXactStatus *pgstat_get_xact_stack_level(int nest_level);
658 : : extern void pgstat_drop_transactional(PgStat_Kind kind, Oid dboid, Oid objoid);
659 : : extern void pgstat_create_transactional(PgStat_Kind kind, Oid dboid, Oid objoid);
660 : :
661 : :
662 : : /*
663 : : * Variables in pgstat.c
664 : : */
665 : :
666 : : extern PGDLLIMPORT PgStat_LocalState pgStatLocal;
667 : :
668 : :
669 : : /*
670 : : * Variables in pgstat_io.c
671 : : */
672 : :
673 : : extern PGDLLIMPORT bool have_iostats;
674 : :
675 : :
676 : : /*
677 : : * Variables in pgstat_slru.c
678 : : */
679 : :
680 : : extern PGDLLIMPORT bool have_slrustats;
681 : :
682 : :
683 : : /*
684 : : * Implementation of inline functions declared above.
685 : : */
686 : :
687 : : /*
688 : : * Helpers for changecount manipulation. See comments around struct
689 : : * PgBackendStatus for details.
690 : : */
691 : :
692 : : static inline void
739 andres@anarazel.de 693 :CBC 10787 : pgstat_begin_changecount_write(uint32 *cc)
694 : : {
695 [ - + ]: 10787 : Assert((*cc & 1) == 0);
696 : :
697 : 10787 : START_CRIT_SECTION();
698 : 10787 : (*cc)++;
699 : 10787 : pg_write_barrier();
700 : 10787 : }
701 : :
702 : : static inline void
703 : 10787 : pgstat_end_changecount_write(uint32 *cc)
704 : : {
705 [ - + ]: 10787 : Assert((*cc & 1) == 1);
706 : :
707 : 10787 : pg_write_barrier();
708 : :
709 : 10787 : (*cc)++;
710 : :
711 [ - + ]: 10787 : END_CRIT_SECTION();
712 : 10787 : }
713 : :
714 : : static inline uint32
715 : 2393 : pgstat_begin_changecount_read(uint32 *cc)
716 : : {
717 : 2393 : uint32 before_cc = *cc;
718 : :
719 [ - + ]: 2393 : CHECK_FOR_INTERRUPTS();
720 : :
721 : 2393 : pg_read_barrier();
722 : :
723 : 2393 : return before_cc;
724 : : }
725 : :
726 : : /*
727 : : * Returns true if the read succeeded, false if it needs to be repeated.
728 : : */
729 : : static inline bool
730 : 2393 : pgstat_end_changecount_read(uint32 *cc, uint32 before_cc)
731 : : {
732 : : uint32 after_cc;
733 : :
734 : 2393 : pg_read_barrier();
735 : :
736 : 2393 : after_cc = *cc;
737 : :
738 : : /* was a write in progress when we started? */
739 [ - + ]: 2393 : if (before_cc & 1)
739 andres@anarazel.de 740 :UBC 0 : return false;
741 : :
742 : : /* did writes start and complete while we read? */
739 andres@anarazel.de 743 :CBC 2393 : return before_cc == after_cc;
744 : : }
745 : :
746 : :
747 : : /*
748 : : * helper function for PgStat_KindInfo->snapshot_cb
749 : : * PgStat_KindInfo->reset_all_cb callbacks.
750 : : *
751 : : * Copies out the specified memory area following change-count protocol.
752 : : */
753 : : static inline void
754 : 2393 : pgstat_copy_changecounted_stats(void *dst, void *src, size_t len,
755 : : uint32 *cc)
756 : : {
757 : : uint32 cc_before;
758 : :
759 : : do
760 : : {
761 : 2393 : cc_before = pgstat_begin_changecount_read(cc);
762 : :
763 : 2393 : memcpy(dst, src, len);
764 : : }
765 [ - + ]: 2393 : while (!pgstat_end_changecount_read(cc, cc_before));
766 : 2393 : }
767 : :
768 : : /* helpers for dshash / simplehash hashtables */
769 : : static inline int
770 : 4303347 : pgstat_cmp_hash_key(const void *a, const void *b, size_t size, void *arg)
771 : : {
534 peter@eisentraut.org 772 [ + - - + ]: 4303347 : Assert(size == sizeof(PgStat_HashKey) && arg == NULL);
739 andres@anarazel.de 773 : 4303347 : return memcmp(a, b, sizeof(PgStat_HashKey));
774 : : }
775 : :
776 : : static inline uint32
777 : 5319480 : pgstat_hash_hash_key(const void *d, size_t size, void *arg)
778 : : {
139 john.naylor@postgres 779 :GNC 5319480 : const char *key = (const char *) d;
780 : :
534 peter@eisentraut.org 781 [ + - - + ]:CBC 5319480 : Assert(size == sizeof(PgStat_HashKey) && arg == NULL);
139 john.naylor@postgres 782 :GNC 5319480 : return fasthash32(key, size, 0);
783 : : }
784 : :
785 : : /*
786 : : * The length of the data portion of a shared memory stats entry (i.e. without
787 : : * transient data such as refcounts, lwlocks, ...).
788 : : */
789 : : static inline size_t
739 andres@anarazel.de 790 :CBC 313954 : pgstat_get_entry_len(PgStat_Kind kind)
791 : : {
792 : 313954 : return pgstat_get_kind_info(kind)->shared_data_len;
793 : : }
794 : :
795 : : /*
796 : : * Returns a pointer to the data portion of a shared memory stats entry.
797 : : */
798 : : static inline void *
799 : 498565 : pgstat_get_entry_data(PgStat_Kind kind, PgStatShared_Common *entry)
800 : : {
801 : 498565 : size_t off = pgstat_get_kind_info(kind)->shared_data_off;
802 : :
803 [ + - - + ]: 498565 : Assert(off != 0 && off < PG_UINT32_MAX);
804 : :
805 : 498565 : return ((char *) (entry)) + off;
806 : : }
807 : :
808 : : #endif /* PGSTAT_INTERNAL_H */
|