pgstat_internal.h 22 KB

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