PostgreSQL Source Code  git master
pgstat.c File Reference
#include "postgres.h"
#include <unistd.h>
#include "access/xact.h"
#include "access/xlog.h"
#include "lib/dshash.h"
#include "pgstat.h"
#include "port/atomics.h"
#include "storage/fd.h"
#include "storage/ipc.h"
#include "storage/lwlock.h"
#include "utils/guc_hooks.h"
#include "utils/memutils.h"
#include "utils/pgstat_internal.h"
#include "utils/timestamp.h"
#include "lib/simplehash.h"
Include dependency graph for pgstat.c:

Go to the source code of this file.

Data Structures

struct  PgStat_SnapshotEntry
 

Macros

#define PGSTAT_MIN_INTERVAL   1000
 
#define PGSTAT_MAX_INTERVAL   60000
 
#define PGSTAT_IDLE_INTERVAL   10000
 
#define PGSTAT_SNAPSHOT_HASH_SIZE   512
 
#define PGSTAT_FILE_ENTRY_END   'E' /* end of file */
 
#define PGSTAT_FILE_ENTRY_FIXED   'F' /* fixed-numbered stats entry */
 
#define PGSTAT_FILE_ENTRY_NAME   'N' /* stats entry identified by name */
 
#define PGSTAT_FILE_ENTRY_HASH
 
#define SH_PREFIX   pgstat_snapshot
 
#define SH_ELEMENT_TYPE   PgStat_SnapshotEntry
 
#define SH_KEY_TYPE   PgStat_HashKey
 
#define SH_KEY   key
 
#define SH_HASH_KEY(tb, key)    pgstat_hash_hash_key(&key, sizeof(PgStat_HashKey), NULL)
 
#define SH_EQUAL(tb, a, b)    pgstat_cmp_hash_key(&a, &b, sizeof(PgStat_HashKey), NULL) == 0
 
#define SH_SCOPE   static inline
 
#define SH_DEFINE
 
#define SH_DECLARE
 
#define write_chunk_s(fpout, ptr)   write_chunk(fpout, ptr, sizeof(*ptr))
 
#define read_chunk_s(fpin, ptr)   read_chunk(fpin, ptr, sizeof(*ptr))
 

Typedefs

typedef struct PgStat_SnapshotEntry PgStat_SnapshotEntry
 

Functions

static void pgstat_write_statsfile (XLogRecPtr redo)
 
static void pgstat_read_statsfile (XLogRecPtr redo)
 
static void pgstat_init_snapshot_fixed (void)
 
static void pgstat_reset_after_failure (void)
 
static bool pgstat_flush_pending_entries (bool nowait)
 
static void pgstat_prep_snapshot (void)
 
static void pgstat_build_snapshot (void)
 
static void pgstat_build_snapshot_fixed (PgStat_Kind kind)
 
static bool pgstat_is_kind_valid (PgStat_Kind kind)
 
void pgstat_restore_stats (XLogRecPtr redo)
 
void pgstat_discard_stats (void)
 
void pgstat_before_server_shutdown (int code, Datum arg)
 
static void pgstat_shutdown_hook (int code, Datum arg)
 
void pgstat_initialize (void)
 
long pgstat_report_stat (bool force)
 
void pgstat_force_next_flush (void)
 
static bool match_db_entries (PgStatShared_HashEntry *entry, Datum match_data)
 
void pgstat_reset_counters (void)
 
void pgstat_reset (PgStat_Kind kind, Oid dboid, uint64 objid)
 
void pgstat_reset_of_kind (PgStat_Kind kind)
 
void pgstat_clear_snapshot (void)
 
void * pgstat_fetch_entry (PgStat_Kind kind, Oid dboid, uint64 objid)
 
TimestampTz pgstat_get_stat_snapshot_timestamp (bool *have_snapshot)
 
bool pgstat_have_entry (PgStat_Kind kind, Oid dboid, uint64 objid)
 
void pgstat_snapshot_fixed (PgStat_Kind kind)
 
PgStat_EntryRefpgstat_prep_pending_entry (PgStat_Kind kind, Oid dboid, uint64 objid, bool *created_entry)
 
PgStat_EntryRefpgstat_fetch_pending_entry (PgStat_Kind kind, Oid dboid, uint64 objid)
 
void pgstat_delete_pending_entry (PgStat_EntryRef *entry_ref)
 
PgStat_Kind pgstat_get_kind_from_str (char *kind_str)
 
const PgStat_KindInfopgstat_get_kind_info (PgStat_Kind kind)
 
void pgstat_register_kind (PgStat_Kind kind, const PgStat_KindInfo *kind_info)
 
static void write_chunk (FILE *fpout, void *ptr, size_t len)
 
static bool read_chunk (FILE *fpin, void *ptr, size_t len)
 
void assign_stats_fetch_consistency (int newval, void *extra)
 

Variables

bool pgstat_track_counts = false
 
int pgstat_fetch_consistency = PGSTAT_FETCH_CONSISTENCY_CACHE
 
PgStat_LocalState pgStatLocal
 
static MemoryContext pgStatPendingContext = NULL
 
static dlist_head pgStatPending = DLIST_STATIC_INIT(pgStatPending)
 
static bool pgStatForceNextFlush = false
 
static bool force_stats_snapshot_clear = false
 
static const PgStat_KindInfo pgstat_kind_builtin_infos [PGSTAT_KIND_BUILTIN_SIZE]
 
static const PgStat_KindInfo ** pgstat_kind_custom_infos = NULL
 

Macro Definition Documentation

◆ PGSTAT_FILE_ENTRY_END

#define PGSTAT_FILE_ENTRY_END   'E' /* end of file */

Definition at line 143 of file pgstat.c.

◆ PGSTAT_FILE_ENTRY_FIXED

#define PGSTAT_FILE_ENTRY_FIXED   'F' /* fixed-numbered stats entry */

Definition at line 144 of file pgstat.c.

◆ PGSTAT_FILE_ENTRY_HASH

#define PGSTAT_FILE_ENTRY_HASH
Value:
'S' /* stats entry identified by
* PgStat_HashKey */

Definition at line 146 of file pgstat.c.

◆ PGSTAT_FILE_ENTRY_NAME

#define PGSTAT_FILE_ENTRY_NAME   'N' /* stats entry identified by name */

Definition at line 145 of file pgstat.c.

◆ PGSTAT_IDLE_INTERVAL

#define PGSTAT_IDLE_INTERVAL   10000

Definition at line 130 of file pgstat.c.

◆ PGSTAT_MAX_INTERVAL

#define PGSTAT_MAX_INTERVAL   60000

Definition at line 128 of file pgstat.c.

◆ PGSTAT_MIN_INTERVAL

#define PGSTAT_MIN_INTERVAL   1000

Definition at line 126 of file pgstat.c.

◆ PGSTAT_SNAPSHOT_HASH_SIZE

#define PGSTAT_SNAPSHOT_HASH_SIZE   512

Definition at line 137 of file pgstat.c.

◆ read_chunk_s

#define read_chunk_s (   fpin,
  ptr 
)    read_chunk(fpin, ptr, sizeof(*ptr))

Definition at line 1726 of file pgstat.c.

◆ SH_DECLARE

#define SH_DECLARE

Definition at line 173 of file pgstat.c.

◆ SH_DEFINE

#define SH_DEFINE

Definition at line 172 of file pgstat.c.

◆ SH_ELEMENT_TYPE

#define SH_ELEMENT_TYPE   PgStat_SnapshotEntry

Definition at line 164 of file pgstat.c.

◆ SH_EQUAL

#define SH_EQUAL (   tb,
  a,
  b 
)     pgstat_cmp_hash_key(&a, &b, sizeof(PgStat_HashKey), NULL) == 0

Definition at line 169 of file pgstat.c.

◆ SH_HASH_KEY

#define SH_HASH_KEY (   tb,
  key 
)     pgstat_hash_hash_key(&key, sizeof(PgStat_HashKey), NULL)

Definition at line 167 of file pgstat.c.

◆ SH_KEY

#define SH_KEY   key

Definition at line 166 of file pgstat.c.

◆ SH_KEY_TYPE

#define SH_KEY_TYPE   PgStat_HashKey

Definition at line 165 of file pgstat.c.

◆ SH_PREFIX

#define SH_PREFIX   pgstat_snapshot

Definition at line 163 of file pgstat.c.

◆ SH_SCOPE

#define SH_SCOPE   static inline

Definition at line 171 of file pgstat.c.

◆ write_chunk_s

#define write_chunk_s (   fpout,
  ptr 
)    write_chunk(fpout, ptr, sizeof(*ptr))

Definition at line 1556 of file pgstat.c.

Typedef Documentation

◆ PgStat_SnapshotEntry

Function Documentation

◆ assign_stats_fetch_consistency()

void assign_stats_fetch_consistency ( int  newval,
void *  extra 
)

Definition at line 2047 of file pgstat.c.

2049 {
2050  /*
2051  * Changing this value in a transaction may cause snapshot state
2052  * inconsistencies, so force a clear of the current snapshot on the next
2053  * snapshot build attempt.
2054  */
#define newval
int pgstat_fetch_consistency
Definition: pgstat.c:204
static bool force_stats_snapshot_clear
Definition: pgstat.c:250

References force_stats_snapshot_clear, newval, and pgstat_fetch_consistency.

◆ match_db_entries()

static bool match_db_entries ( PgStatShared_HashEntry entry,
Datum  match_data 
)
static

Definition at line 817 of file pgstat.c.

819 {
820  return entry->key.dboid == DatumGetObjectId(MyDatabaseId);
Oid MyDatabaseId
Definition: globals.c:93
static Oid DatumGetObjectId(Datum X)
Definition: postgres.h:242

References DatumGetObjectId(), PgStat_HashKey::dboid, PgStatShared_HashEntry::key, and MyDatabaseId.

Referenced by pgstat_reset_counters().

◆ pgstat_before_server_shutdown()

void pgstat_before_server_shutdown ( int  code,
Datum  arg 
)

Definition at line 532 of file pgstat.c.

534 {
535  Assert(pgStatLocal.shmem != NULL);
537 
538  /*
539  * Stats should only be reported after pgstat_initialize() and before
540  * pgstat_shutdown(). This is a convenient point to catch most violations
541  * of this rule.
542  */
543  Assert(pgstat_is_initialized && !pgstat_is_shutdown);
544 
545  /* flush out our own pending changes before writing out */
546  pgstat_report_stat(true);
547 
548  /*
549  * Only write out file during normal shutdown. Don't even signal that
550  * we've shutdown during irregular shutdowns, because the shutdown
551  * sequence isn't coordinated to ensure this backend shuts down last.
552  */
553  if (code == 0)
554  {
555  pgStatLocal.shmem->is_shutdown = true;
557  }
#define Assert(condition)
Definition: c.h:849
long pgstat_report_stat(bool force)
Definition: pgstat.c:660
static void pgstat_write_statsfile(XLogRecPtr redo)
Definition: pgstat.c:1563
PgStat_LocalState pgStatLocal
Definition: pgstat.c:212
PgStat_ShmemControl * shmem
XLogRecPtr GetRedoRecPtr(void)
Definition: xlog.c:6436

References Assert, GetRedoRecPtr(), PgStat_ShmemControl::is_shutdown, pgstat_report_stat(), pgstat_write_statsfile(), pgStatLocal, and PgStat_LocalState::shmem.

Referenced by CheckpointerMain(), and InitPostgres().

◆ pgstat_build_snapshot()

static void pgstat_build_snapshot ( void  )
static

Definition at line 1114 of file pgstat.c.

1116 {
1117  dshash_seq_status hstat;
1119 
1120  /* should only be called when we need a snapshot */
1122 
1123  /* snapshot already built */
1125  return;
1126 
1128 
1129  Assert(pgStatLocal.snapshot.stats->members == 0);
1130 
1132 
1133  /*
1134  * Snapshot all variable stats.
1135  */
1136  dshash_seq_init(&hstat, pgStatLocal.shared_hash, false);
1137  while ((p = dshash_seq_next(&hstat)) != NULL)
1138  {
1139  PgStat_Kind kind = p->key.kind;
1140  const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind);
1141  bool found;
1142  PgStat_SnapshotEntry *entry;
1143  PgStatShared_Common *stats_data;
1144 
1145  /*
1146  * Check if the stats object should be included in the snapshot.
1147  * Unless the stats kind can be accessed from all databases (e.g.,
1148  * database stats themselves), we only include stats for the current
1149  * database or objects not associated with a database (e.g. shared
1150  * relations).
1151  */
1152  if (p->key.dboid != MyDatabaseId &&
1153  p->key.dboid != InvalidOid &&
1154  !kind_info->accessed_across_databases)
1155  continue;
1156 
1157  if (p->dropped)
1158  continue;
1159 
1161 
1162  stats_data = dsa_get_address(pgStatLocal.dsa, p->body);
1163  Assert(stats_data);
1164 
1165  entry = pgstat_snapshot_insert(pgStatLocal.snapshot.stats, p->key, &found);
1166  Assert(!found);
1167 
1169  kind_info->shared_size);
1170 
1171  /*
1172  * Acquire the LWLock directly instead of using
1173  * pg_stat_lock_entry_shared() which requires a reference.
1174  */
1175  LWLockAcquire(&stats_data->lock, LW_SHARED);
1176  memcpy(entry->data,
1177  pgstat_get_entry_data(kind, stats_data),
1178  kind_info->shared_size);
1179  LWLockRelease(&stats_data->lock);
1180  }
1181  dshash_seq_term(&hstat);
1182 
1183  /*
1184  * Build snapshot of all fixed-numbered stats.
1185  */
1186  for (PgStat_Kind kind = PGSTAT_KIND_MIN; kind <= PGSTAT_KIND_MAX; kind++)
1187  {
1188  const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind);
1189 
1190  if (!kind_info)
1191  continue;
1192  if (!kind_info->fixed_amount)
1193  {
1194  Assert(kind_info->snapshot_cb == NULL);
1195  continue;
1196  }
1197 
1199  }
1200 
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition: atomics.h:239
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1644
void * dsa_get_address(dsa_area *area, dsa_pointer dp)
Definition: dsa.c:942
void dshash_seq_init(dshash_seq_status *status, dshash_table *hash_table, bool exclusive)
Definition: dshash.c:638
void dshash_seq_term(dshash_seq_status *status)
Definition: dshash.c:747
void * dshash_seq_next(dshash_seq_status *status)
Definition: dshash.c:657
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1168
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1781
@ LW_SHARED
Definition: lwlock.h:115
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1181
const PgStat_KindInfo * pgstat_get_kind_info(PgStat_Kind kind)
Definition: pgstat.c:1430
static void pgstat_prep_snapshot(void)
Definition: pgstat.c:1093
static void pgstat_build_snapshot_fixed(PgStat_Kind kind)
Definition: pgstat.c:1204
@ PGSTAT_FETCH_CONSISTENCY_SNAPSHOT
Definition: pgstat.h:103
#define PgStat_Kind
Definition: pgstat.h:37
#define PGSTAT_KIND_MAX
Definition: pgstat.h:41
#define PGSTAT_KIND_MIN
Definition: pgstat.h:40
static void * pgstat_get_entry_data(PgStat_Kind kind, PgStatShared_Common *entry)
#define InvalidOid
Definition: postgres_ext.h:36
pg_atomic_uint32 refcount
PgStat_Kind kind
bool accessed_across_databases
void(* snapshot_cb)(void)
PgStat_Snapshot snapshot
dshash_table * shared_hash
TimestampTz snapshot_timestamp
MemoryContext context
PgStat_FetchConsistency mode
struct pgstat_snapshot_hash * stats

References PgStat_KindInfo::accessed_across_databases, Assert, PgStatShared_HashEntry::body, PgStat_Snapshot::context, PgStat_SnapshotEntry::data, PgStat_HashKey::dboid, PgStatShared_HashEntry::dropped, PgStat_LocalState::dsa, dsa_get_address(), dshash_seq_init(), dshash_seq_next(), dshash_seq_term(), PgStat_KindInfo::fixed_amount, GetCurrentTimestamp(), InvalidOid, PgStatShared_HashEntry::key, PgStat_HashKey::kind, PgStatShared_Common::lock, LW_SHARED, LWLockAcquire(), LWLockRelease(), MemoryContextAlloc(), PgStat_Snapshot::mode, MyDatabaseId, pg_atomic_read_u32(), pgstat_build_snapshot_fixed(), pgstat_fetch_consistency, PGSTAT_FETCH_CONSISTENCY_SNAPSHOT, pgstat_get_entry_data(), pgstat_get_kind_info(), PgStat_Kind, PGSTAT_KIND_MAX, PGSTAT_KIND_MIN, pgstat_prep_snapshot(), pgStatLocal, PgStatShared_HashEntry::refcount, PgStat_LocalState::shared_hash, PgStat_KindInfo::shared_size, PgStat_LocalState::snapshot, PgStat_KindInfo::snapshot_cb, PgStat_Snapshot::snapshot_timestamp, and PgStat_Snapshot::stats.

Referenced by pgstat_fetch_entry(), and pgstat_snapshot_fixed().

◆ pgstat_build_snapshot_fixed()

static void pgstat_build_snapshot_fixed ( PgStat_Kind  kind)
static

Definition at line 1204 of file pgstat.c.

1206 {
1207  const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind);
1208  int idx;
1209  bool *valid;
1210 
1211  /* Position in fixed_valid or custom_valid */
1212  if (pgstat_is_kind_builtin(kind))
1213  {
1214  idx = kind;
1216  }
1217  else
1218  {
1219  idx = kind - PGSTAT_KIND_CUSTOM_MIN;
1221  }
1222 
1223  Assert(kind_info->fixed_amount);
1224  Assert(kind_info->snapshot_cb != NULL);
1225 
1227  {
1228  /* rebuild every time */
1229  valid[idx] = false;
1230  }
1231  else if (valid[idx])
1232  {
1233  /* in snapshot mode we shouldn't get called again */
1235  return;
1236  }
1237 
1238  Assert(!valid[idx]);
1239 
1240  kind_info->snapshot_cb();
1241 
1242  Assert(!valid[idx]);
1243  valid[idx] = true;
Datum idx(PG_FUNCTION_ARGS)
Definition: _int_op.c:259
static bool pgstat_is_kind_builtin(PgStat_Kind kind)
Definition: pgstat.h:80
@ PGSTAT_FETCH_CONSISTENCY_NONE
Definition: pgstat.h:101
@ PGSTAT_FETCH_CONSISTENCY_CACHE
Definition: pgstat.h:102
#define PGSTAT_KIND_CUSTOM_MIN
Definition: pgstat.h:68
bool custom_valid[PGSTAT_KIND_CUSTOM_SIZE]
bool fixed_valid[PGSTAT_KIND_BUILTIN_SIZE]

References Assert, PgStat_Snapshot::custom_valid, PgStat_KindInfo::fixed_amount, PgStat_Snapshot::fixed_valid, idx(), pgstat_fetch_consistency, PGSTAT_FETCH_CONSISTENCY_CACHE, PGSTAT_FETCH_CONSISTENCY_NONE, pgstat_get_kind_info(), pgstat_is_kind_builtin(), PGSTAT_KIND_CUSTOM_MIN, pgStatLocal, PgStat_LocalState::snapshot, and PgStat_KindInfo::snapshot_cb.

Referenced by pgstat_build_snapshot(), pgstat_snapshot_fixed(), and pgstat_write_statsfile().

◆ pgstat_clear_snapshot()

void pgstat_clear_snapshot ( void  )

Definition at line 896 of file pgstat.c.

898 {
900 
901  memset(&pgStatLocal.snapshot.fixed_valid, 0,
903  memset(&pgStatLocal.snapshot.custom_valid, 0,
905  pgStatLocal.snapshot.stats = NULL;
907 
908  /* Release memory, if any was allocated */
910  {
912 
913  /* Reset variables */
915  }
916 
917  /*
918  * Historically the backend_status.c facilities lived in this file, and
919  * were reset with the same function. For now keep it that way, and
920  * forward the reset request.
921  */
923 
924  /* Reset this flag, as it may be possible that a cleanup was forced. */
void pgstat_clear_backend_activity_snapshot(void)
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:454
#define pgstat_assert_is_up()

References PgStat_Snapshot::context, PgStat_Snapshot::custom_valid, PgStat_Snapshot::fixed_valid, force_stats_snapshot_clear, MemoryContextDelete(), PgStat_Snapshot::mode, pgstat_assert_is_up, pgstat_clear_backend_activity_snapshot(), PGSTAT_FETCH_CONSISTENCY_NONE, pgStatLocal, PgStat_LocalState::snapshot, and PgStat_Snapshot::stats.

Referenced by AtEOXact_PgStat(), pg_stat_clear_snapshot(), pgstat_get_stat_snapshot_timestamp(), pgstat_prep_snapshot(), pgstat_snapshot_fixed(), and PostPrepare_PgStat().

◆ pgstat_delete_pending_entry()

void pgstat_delete_pending_entry ( PgStat_EntryRef entry_ref)

Definition at line 1310 of file pgstat.c.

1312 {
1313  PgStat_Kind kind = entry_ref->shared_entry->key.kind;
1314  const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind);
1315  void *pending_data = entry_ref->pending;
1316 
1317  Assert(pending_data != NULL);
1318  /* !fixed_amount stats should be handled explicitly */
1319  Assert(!pgstat_get_kind_info(kind)->fixed_amount);
1320 
1321  if (kind_info->delete_pending_cb)
1322  kind_info->delete_pending_cb(entry_ref);
1323 
1324  pfree(pending_data);
1325  entry_ref->pending = NULL;
1326 
1327  dlist_delete(&entry_ref->pending_node);
static void dlist_delete(dlist_node *node)
Definition: ilist.h:405
void pfree(void *pointer)
Definition: mcxt.c:1521
PgStatShared_HashEntry * shared_entry
dlist_node pending_node
void(* delete_pending_cb)(PgStat_EntryRef *sr)

References Assert, PgStat_KindInfo::delete_pending_cb, dlist_delete(), PgStatShared_HashEntry::key, PgStat_HashKey::kind, PgStat_EntryRef::pending, PgStat_EntryRef::pending_node, pfree(), pgstat_get_kind_info(), PgStat_Kind, and PgStat_EntryRef::shared_entry.

Referenced by pgstat_flush_pending_entries(), and pgstat_release_entry_ref().

◆ pgstat_discard_stats()

void pgstat_discard_stats ( void  )

Definition at line 489 of file pgstat.c.

491 {
492  int ret;
493 
494  /* NB: this needs to be done even in single user mode */
495 
496  ret = unlink(PGSTAT_STAT_PERMANENT_FILENAME);
497  if (ret != 0)
498  {
499  if (errno == ENOENT)
500  elog(DEBUG2,
501  "didn't need to unlink permanent stats file \"%s\" - didn't exist",
503  else
504  ereport(LOG,
506  errmsg("could not unlink permanent statistics file \"%s\": %m",
508  }
509  else
510  {
511  ereport(DEBUG2,
513  errmsg_internal("unlinked permanent statistics file \"%s\"",
515  }
516 
517  /*
518  * Reset stats contents. This will set reset timestamps of fixed-numbered
519  * stats to the current time (no variable stats exist).
520  */
int errmsg_internal(const char *fmt,...)
Definition: elog.c:1157
int errcode_for_file_access(void)
Definition: elog.c:876
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define LOG
Definition: elog.h:31
#define DEBUG2
Definition: elog.h:29
#define elog(elevel,...)
Definition: elog.h:225
#define ereport(elevel,...)
Definition: elog.h:149
static void pgstat_reset_after_failure(void)
Definition: pgstat.c:2024
#define PGSTAT_STAT_PERMANENT_FILENAME
Definition: pgstat.h:30

References DEBUG2, elog, ereport, errcode_for_file_access(), errmsg(), errmsg_internal(), LOG, pgstat_reset_after_failure(), and PGSTAT_STAT_PERMANENT_FILENAME.

Referenced by StartupXLOG().

◆ pgstat_fetch_entry()

void* pgstat_fetch_entry ( PgStat_Kind  kind,
Oid  dboid,
uint64  objid 
)

Definition at line 928 of file pgstat.c.

930 {
932  PgStat_EntryRef *entry_ref;
933  void *stats_data;
934  const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind);
935 
936  /* should be called from backends */
938  Assert(!kind_info->fixed_amount);
939 
941 
942  key.kind = kind;
943  key.dboid = dboid;
944  key.objid = objid;
945 
946  /* if we need to build a full snapshot, do so */
949 
950  /* if caching is desired, look up in cache */
952  {
953  PgStat_SnapshotEntry *entry = NULL;
954 
955  entry = pgstat_snapshot_lookup(pgStatLocal.snapshot.stats, key);
956 
957  if (entry)
958  return entry->data;
959 
960  /*
961  * If we built a full snapshot and the key is not in
962  * pgStatLocal.snapshot.stats, there are no matching stats.
963  */
965  return NULL;
966  }
967 
969 
970  entry_ref = pgstat_get_entry_ref(kind, dboid, objid, false, NULL);
971 
972  if (entry_ref == NULL || entry_ref->shared_entry->dropped)
973  {
974  /* create empty entry when using PGSTAT_FETCH_CONSISTENCY_CACHE */
976  {
977  PgStat_SnapshotEntry *entry = NULL;
978  bool found;
979 
980  entry = pgstat_snapshot_insert(pgStatLocal.snapshot.stats, key, &found);
981  Assert(!found);
982  entry->data = NULL;
983  }
984  return NULL;
985  }
986 
987  /*
988  * Allocate in caller's context for PGSTAT_FETCH_CONSISTENCY_NONE,
989  * otherwise we could quickly end up with a fair bit of memory used due to
990  * repeated accesses.
991  */
993  stats_data = palloc(kind_info->shared_data_len);
994  else
996  kind_info->shared_data_len);
997 
998  pgstat_lock_entry_shared(entry_ref, false);
999  memcpy(stats_data,
1000  pgstat_get_entry_data(kind, entry_ref->shared_stats),
1001  kind_info->shared_data_len);
1002  pgstat_unlock_entry(entry_ref);
1003 
1005  {
1006  PgStat_SnapshotEntry *entry = NULL;
1007  bool found;
1008 
1009  entry = pgstat_snapshot_insert(pgStatLocal.snapshot.stats, key, &found);
1010  entry->data = stats_data;
1011  }
1012 
1013  return stats_data;
bool IsUnderPostmaster
Definition: globals.c:119
bool IsPostmasterEnvironment
Definition: globals.c:118
void * palloc(Size size)
Definition: mcxt.c:1317
static void pgstat_build_snapshot(void)
Definition: pgstat.c:1114
bool pgstat_lock_entry_shared(PgStat_EntryRef *entry_ref, bool nowait)
Definition: pgstat_shmem.c:626
PgStat_EntryRef * pgstat_get_entry_ref(PgStat_Kind kind, Oid dboid, uint64 objid, bool create, bool *created_entry)
Definition: pgstat_shmem.c:432
void pgstat_unlock_entry(PgStat_EntryRef *entry_ref)
Definition: pgstat_shmem.c:638
PgStatShared_Common * shared_stats

References Assert, PgStat_Snapshot::context, PgStat_SnapshotEntry::data, PgStatShared_HashEntry::dropped, PgStat_KindInfo::fixed_amount, IsPostmasterEnvironment, IsUnderPostmaster, sort-test::key, MemoryContextAlloc(), PgStat_Snapshot::mode, palloc(), pgstat_build_snapshot(), pgstat_fetch_consistency, PGSTAT_FETCH_CONSISTENCY_CACHE, PGSTAT_FETCH_CONSISTENCY_NONE, PGSTAT_FETCH_CONSISTENCY_SNAPSHOT, pgstat_get_entry_data(), pgstat_get_entry_ref(), pgstat_get_kind_info(), pgstat_lock_entry_shared(), pgstat_prep_snapshot(), pgstat_unlock_entry(), pgStatLocal, PgStat_KindInfo::shared_data_len, PgStat_EntryRef::shared_entry, PgStat_EntryRef::shared_stats, PgStat_LocalState::snapshot, and PgStat_Snapshot::stats.

Referenced by pgstat_fetch_replslot(), pgstat_fetch_stat_dbentry(), pgstat_fetch_stat_funcentry(), pgstat_fetch_stat_injentry(), pgstat_fetch_stat_subscription(), and pgstat_fetch_stat_tabentry_ext().

◆ pgstat_fetch_pending_entry()

PgStat_EntryRef* pgstat_fetch_pending_entry ( PgStat_Kind  kind,
Oid  dboid,
uint64  objid 
)

Definition at line 1297 of file pgstat.c.

1299 {
1300  PgStat_EntryRef *entry_ref;
1301 
1302  entry_ref = pgstat_get_entry_ref(kind, dboid, objid, false, NULL);
1303 
1304  if (entry_ref == NULL || entry_ref->pending == NULL)
1305  return NULL;
1306 
1307  return entry_ref;

References PgStat_EntryRef::pending, and pgstat_get_entry_ref().

Referenced by find_funcstat_entry(), and find_tabstat_entry().

◆ pgstat_flush_pending_entries()

static bool pgstat_flush_pending_entries ( bool  nowait)
static

Definition at line 1334 of file pgstat.c.

1336 {
1337  bool have_pending = false;
1338  dlist_node *cur = NULL;
1339 
1340  /*
1341  * Need to be a bit careful iterating over the list of pending entries.
1342  * Processing a pending entry may queue further pending entries to the end
1343  * of the list that we want to process, so a simple iteration won't do.
1344  * Further complicating matters is that we want to delete the current
1345  * entry in each iteration from the list if we flushed successfully.
1346  *
1347  * So we just keep track of the next pointer in each loop iteration.
1348  */
1351 
1352  while (cur)
1353  {
1354  PgStat_EntryRef *entry_ref =
1355  dlist_container(PgStat_EntryRef, pending_node, cur);
1356  PgStat_HashKey key = entry_ref->shared_entry->key;
1357  PgStat_Kind kind = key.kind;
1358  const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind);
1359  bool did_flush;
1360  dlist_node *next;
1361 
1362  Assert(!kind_info->fixed_amount);
1363  Assert(kind_info->flush_pending_cb != NULL);
1364 
1365  /* flush the stats, if possible */
1366  did_flush = kind_info->flush_pending_cb(entry_ref, nowait);
1367 
1368  Assert(did_flush || nowait);
1369 
1370  /* determine next entry, before deleting the pending entry */
1373  else
1374  next = NULL;
1375 
1376  /* if successfully flushed, remove entry */
1377  if (did_flush)
1378  pgstat_delete_pending_entry(entry_ref);
1379  else
1380  have_pending = true;
1381 
1382  cur = next;
1383  }
1384 
1385  Assert(dlist_is_empty(&pgStatPending) == !have_pending);
1386 
1387  return have_pending;
static int32 next
Definition: blutils.c:222
struct cursor * cur
Definition: ecpg.c:28
static bool dlist_has_next(const dlist_head *head, const dlist_node *node)
Definition: ilist.h:503
static dlist_node * dlist_next_node(dlist_head *head, dlist_node *node)
Definition: ilist.h:537
static bool dlist_is_empty(const dlist_head *head)
Definition: ilist.h:336
static dlist_node * dlist_head_node(dlist_head *head)
Definition: ilist.h:565
#define dlist_container(type, membername, ptr)
Definition: ilist.h:593
void pgstat_delete_pending_entry(PgStat_EntryRef *entry_ref)
Definition: pgstat.c:1310
static dlist_head pgStatPending
Definition: pgstat.c:237
bool(* flush_pending_cb)(PgStat_EntryRef *sr, bool nowait)

References Assert, cur, dlist_container, dlist_has_next(), dlist_head_node(), dlist_is_empty(), dlist_next_node(), PgStat_KindInfo::fixed_amount, PgStat_KindInfo::flush_pending_cb, PgStatShared_HashEntry::key, sort-test::key, next, pgstat_delete_pending_entry(), pgstat_get_kind_info(), PgStat_Kind, pgStatPending, and PgStat_EntryRef::shared_entry.

Referenced by pgstat_report_stat().

◆ pgstat_force_next_flush()

void pgstat_force_next_flush ( void  )

Definition at line 808 of file pgstat.c.

810 {
811  pgStatForceNextFlush = true;
static bool pgStatForceNextFlush
Definition: pgstat.c:244

References pgStatForceNextFlush.

Referenced by pg_stat_force_next_flush().

◆ pgstat_get_kind_from_str()

PgStat_Kind pgstat_get_kind_from_str ( char *  kind_str)

Definition at line 1396 of file pgstat.c.

1398 {
1399  for (PgStat_Kind kind = PGSTAT_KIND_BUILTIN_MIN; kind <= PGSTAT_KIND_BUILTIN_MAX; kind++)
1400  {
1401  if (pg_strcasecmp(kind_str, pgstat_kind_builtin_infos[kind].name) == 0)
1402  return kind;
1403  }
1404 
1405  /* Check the custom set of cumulative stats */
1407  {
1408  for (PgStat_Kind kind = PGSTAT_KIND_CUSTOM_MIN; kind <= PGSTAT_KIND_CUSTOM_MAX; kind++)
1409  {
1411 
1413  pg_strcasecmp(kind_str, pgstat_kind_custom_infos[idx]->name) == 0)
1414  return kind;
1415  }
1416  }
1417 
1418  ereport(ERROR,
1419  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1420  errmsg("invalid statistics kind: \"%s\"", kind_str)));
1421  return PGSTAT_KIND_INVALID; /* avoid compiler warnings */
unsigned int uint32
Definition: c.h:506
int errcode(int sqlerrcode)
Definition: elog.c:853
#define ERROR
Definition: elog.h:39
static const PgStat_KindInfo ** pgstat_kind_custom_infos
Definition: pgstat.c:464
static const PgStat_KindInfo pgstat_kind_builtin_infos[PGSTAT_KIND_BUILTIN_SIZE]
Definition: pgstat.c:276
#define PGSTAT_KIND_CUSTOM_MAX
Definition: pgstat.h:69
#define PGSTAT_KIND_BUILTIN_MAX
Definition: pgstat.h:62
#define PGSTAT_KIND_INVALID
Definition: pgstat.h:44
#define PGSTAT_KIND_BUILTIN_MIN
Definition: pgstat.h:61
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
const char * name

References ereport, errcode(), errmsg(), ERROR, idx(), name, pg_strcasecmp(), PgStat_Kind, pgstat_kind_builtin_infos, PGSTAT_KIND_BUILTIN_MAX, PGSTAT_KIND_BUILTIN_MIN, pgstat_kind_custom_infos, PGSTAT_KIND_CUSTOM_MAX, PGSTAT_KIND_CUSTOM_MIN, and PGSTAT_KIND_INVALID.

Referenced by pg_stat_have_stats().

◆ pgstat_get_kind_info()

◆ pgstat_get_stat_snapshot_timestamp()

TimestampTz pgstat_get_stat_snapshot_timestamp ( bool have_snapshot)

Definition at line 1021 of file pgstat.c.

1023 {
1026 
1028  {
1029  *have_snapshot = true;
1031  }
1032 
1033  *have_snapshot = false;
1034 
1035  return 0;
void pgstat_clear_snapshot(void)
Definition: pgstat.c:896

References force_stats_snapshot_clear, PgStat_Snapshot::mode, pgstat_clear_snapshot(), PGSTAT_FETCH_CONSISTENCY_SNAPSHOT, pgStatLocal, PgStat_LocalState::snapshot, and PgStat_Snapshot::snapshot_timestamp.

Referenced by pg_stat_get_snapshot_timestamp().

◆ pgstat_have_entry()

bool pgstat_have_entry ( PgStat_Kind  kind,
Oid  dboid,
uint64  objid 
)

Definition at line 1038 of file pgstat.c.

1040 {
1041  /* fixed-numbered stats always exist */
1042  if (pgstat_get_kind_info(kind)->fixed_amount)
1043  return true;
1044 
1045  return pgstat_get_entry_ref(kind, dboid, objid, false, NULL) != NULL;

References pgstat_get_entry_ref(), and pgstat_get_kind_info().

Referenced by pg_stat_have_stats().

◆ pgstat_init_snapshot_fixed()

static void pgstat_init_snapshot_fixed ( void  )
static

Definition at line 1074 of file pgstat.c.

1076 {
1077  /*
1078  * Initialize fixed-numbered statistics data in snapshots, only for custom
1079  * stats kinds.
1080  */
1081  for (PgStat_Kind kind = PGSTAT_KIND_CUSTOM_MIN; kind <= PGSTAT_KIND_CUSTOM_MAX; kind++)
1082  {
1083  const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind);
1084 
1085  if (!kind_info || !kind_info->fixed_amount)
1086  continue;
1087 
1090  }
MemoryContext TopMemoryContext
Definition: mcxt.c:149
void * custom_data[PGSTAT_KIND_CUSTOM_SIZE]

References PgStat_Snapshot::custom_data, PgStat_KindInfo::fixed_amount, MemoryContextAlloc(), pgstat_get_kind_info(), PgStat_Kind, PGSTAT_KIND_CUSTOM_MAX, PGSTAT_KIND_CUSTOM_MIN, pgStatLocal, PgStat_KindInfo::shared_data_len, PgStat_LocalState::snapshot, and TopMemoryContext.

Referenced by pgstat_initialize().

◆ pgstat_initialize()

void pgstat_initialize ( void  )

Definition at line 607 of file pgstat.c.

609 {
610  Assert(!pgstat_is_initialized);
611 
613 
615 
616  /* Backend initialization callbacks */
617  for (PgStat_Kind kind = PGSTAT_KIND_MIN; kind <= PGSTAT_KIND_MAX; kind++)
618  {
619  const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind);
620 
621  if (kind_info == NULL || kind_info->init_backend_cb == NULL)
622  continue;
623 
624  kind_info->init_backend_cb();
625  }
626 
627  /* Set up a process-exit hook to clean up */
629 
630 #ifdef USE_ASSERT_CHECKING
631  pgstat_is_initialized = true;
632 #endif
void before_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:337
static void pgstat_init_snapshot_fixed(void)
Definition: pgstat.c:1074
static void pgstat_shutdown_hook(int code, Datum arg)
Definition: pgstat.c:573
void pgstat_attach_shmem(void)
Definition: pgstat_shmem.c:244
void(* init_backend_cb)(void)

References Assert, before_shmem_exit(), PgStat_KindInfo::init_backend_cb, pgstat_attach_shmem(), pgstat_get_kind_info(), pgstat_init_snapshot_fixed(), PgStat_Kind, PGSTAT_KIND_MAX, PGSTAT_KIND_MIN, and pgstat_shutdown_hook().

Referenced by BaseInit().

◆ pgstat_is_kind_valid()

static bool pgstat_is_kind_valid ( PgStat_Kind  kind)
inlinestatic

◆ pgstat_prep_pending_entry()

PgStat_EntryRef* pgstat_prep_pending_entry ( PgStat_Kind  kind,
Oid  dboid,
uint64  objid,
bool created_entry 
)

Definition at line 1259 of file pgstat.c.

1261 {
1262  PgStat_EntryRef *entry_ref;
1263 
1264  /* need to be able to flush out */
1265  Assert(pgstat_get_kind_info(kind)->flush_pending_cb != NULL);
1266 
1268  {
1271  "PgStat Pending",
1273  }
1274 
1275  entry_ref = pgstat_get_entry_ref(kind, dboid, objid,
1276  true, created_entry);
1277 
1278  if (entry_ref->pending == NULL)
1279  {
1280  size_t entrysize = pgstat_get_kind_info(kind)->pending_size;
1281 
1282  Assert(entrysize != (size_t) -1);
1283 
1284  entry_ref->pending = MemoryContextAllocZero(pgStatPendingContext, entrysize);
1286  }
1287 
1288  return entry_ref;
#define unlikely(x)
Definition: c.h:314
static void dlist_push_tail(dlist_head *head, dlist_node *node)
Definition: ilist.h:364
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:1215
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:170
static MemoryContext pgStatPendingContext
Definition: pgstat.c:229

References ALLOCSET_SMALL_SIZES, AllocSetContextCreate, Assert, dlist_push_tail(), MemoryContextAllocZero(), PgStat_EntryRef::pending, PgStat_EntryRef::pending_node, PgStat_KindInfo::pending_size, pgstat_get_entry_ref(), pgstat_get_kind_info(), pgStatPending, pgStatPendingContext, TopMemoryContext, and unlikely.

Referenced by pgstat_init_function_usage(), pgstat_prep_database_pending(), pgstat_prep_relation_pending(), pgstat_report_subscription_conflict(), and pgstat_report_subscription_error().

◆ pgstat_prep_snapshot()

◆ pgstat_read_statsfile()

static void pgstat_read_statsfile ( XLogRecPtr  redo)
static

Definition at line 1735 of file pgstat.c.

1737 {
1738  FILE *fpin;
1739  int32 format_id;
1740  bool found;
1741  const char *statfile = PGSTAT_STAT_PERMANENT_FILENAME;
1743  XLogRecPtr file_redo;
1744 
1745  /* shouldn't be called from postmaster */
1747 
1748  elog(DEBUG2, "reading stats file \"%s\" with redo %X/%X", statfile,
1749  LSN_FORMAT_ARGS(redo));
1750 
1751  /*
1752  * Try to open the stats file. If it doesn't exist, the backends simply
1753  * returns zero for anything and statistics simply starts from scratch
1754  * with empty counters.
1755  *
1756  * ENOENT is a possibility if stats collection was previously disabled or
1757  * has not yet written the stats file for the first time. Any other
1758  * failure condition is suspicious.
1759  */
1760  if ((fpin = AllocateFile(statfile, PG_BINARY_R)) == NULL)
1761  {
1762  if (errno != ENOENT)
1763  ereport(LOG,
1765  errmsg("could not open statistics file \"%s\": %m",
1766  statfile)));
1768  return;
1769  }
1770 
1771  /*
1772  * Verify it's of the expected format.
1773  */
1774  if (!read_chunk_s(fpin, &format_id))
1775  {
1776  elog(WARNING, "could not read format ID");
1777  goto error;
1778  }
1779 
1780  if (format_id != PGSTAT_FILE_FORMAT_ID)
1781  {
1782  elog(WARNING, "found incorrect format ID %d (expected %d)",
1783  format_id, PGSTAT_FILE_FORMAT_ID);
1784  goto error;
1785  }
1786 
1787  /*
1788  * Read the redo LSN stored in the file.
1789  */
1790  if (!read_chunk_s(fpin, &file_redo))
1791  {
1792  elog(WARNING, "could not read redo LSN");
1793  goto error;
1794  }
1795 
1796  if (file_redo != redo)
1797  {
1798  elog(WARNING, "found incorrect redo LSN %X/%X (expected %X/%X)",
1799  LSN_FORMAT_ARGS(file_redo), LSN_FORMAT_ARGS(redo));
1800  goto error;
1801  }
1802 
1803  /*
1804  * We found an existing statistics file. Read it and put all the stats
1805  * data into place.
1806  */
1807  for (;;)
1808  {
1809  int t = fgetc(fpin);
1810 
1811  switch (t)
1812  {
1814  {
1815  PgStat_Kind kind;
1816  const PgStat_KindInfo *info;
1817  char *ptr;
1818 
1819  /* entry for fixed-numbered stats */
1820  if (!read_chunk_s(fpin, &kind))
1821  {
1822  elog(WARNING, "could not read stats kind for entry of type %c", t);
1823  goto error;
1824  }
1825 
1826  if (!pgstat_is_kind_valid(kind))
1827  {
1828  elog(WARNING, "invalid stats kind %u for entry of type %c",
1829  kind, t);
1830  goto error;
1831  }
1832 
1833  info = pgstat_get_kind_info(kind);
1834  if (!info)
1835  {
1836  elog(WARNING, "could not find information of kind %u for entry of type %c",
1837  kind, t);
1838  goto error;
1839  }
1840 
1841  if (!info->fixed_amount)
1842  {
1843  elog(WARNING, "invalid fixed_amount in stats kind %u for entry of type %c",
1844  kind, t);
1845  goto error;
1846  }
1847 
1848  /* Load back stats into shared memory */
1849  if (pgstat_is_kind_builtin(kind))
1850  ptr = ((char *) shmem) + info->shared_ctl_off +
1851  info->shared_data_off;
1852  else
1853  {
1854  int idx = kind - PGSTAT_KIND_CUSTOM_MIN;
1855 
1856  ptr = ((char *) shmem->custom_data[idx]) +
1857  info->shared_data_off;
1858  }
1859 
1860  if (!read_chunk(fpin, ptr, info->shared_data_len))
1861  {
1862  elog(WARNING, "could not read data of stats kind %u for entry of type %c with size %u",
1863  kind, t, info->shared_data_len);
1864  goto error;
1865  }
1866 
1867  break;
1868  }
1871  {
1874  PgStatShared_Common *header;
1875 
1877 
1878  if (t == PGSTAT_FILE_ENTRY_HASH)
1879  {
1880  /* normal stats entry, identified by PgStat_HashKey */
1881  if (!read_chunk_s(fpin, &key))
1882  {
1883  elog(WARNING, "could not read key for entry of type %c", t);
1884  goto error;
1885  }
1886 
1887  if (!pgstat_is_kind_valid(key.kind))
1888  {
1889  elog(WARNING, "invalid stats kind for entry %u/%u/%llu of type %c",
1890  key.kind, key.dboid,
1891  (unsigned long long) key.objid, t);
1892  goto error;
1893  }
1894  }
1895  else
1896  {
1897  /* stats entry identified by name on disk (e.g. slots) */
1898  const PgStat_KindInfo *kind_info = NULL;
1899  PgStat_Kind kind;
1900  NameData name;
1901 
1902  if (!read_chunk_s(fpin, &kind))
1903  {
1904  elog(WARNING, "could not read stats kind for entry of type %c", t);
1905  goto error;
1906  }
1907  if (!read_chunk_s(fpin, &name))
1908  {
1909  elog(WARNING, "could not read name of stats kind %u for entry of type %c",
1910  kind, t);
1911  goto error;
1912  }
1913  if (!pgstat_is_kind_valid(kind))
1914  {
1915  elog(WARNING, "invalid stats kind %u for entry of type %c",
1916  kind, t);
1917  goto error;
1918  }
1919 
1920  kind_info = pgstat_get_kind_info(kind);
1921  if (!kind_info)
1922  {
1923  elog(WARNING, "could not find information of kind %u for entry of type %c",
1924  kind, t);
1925  goto error;
1926  }
1927 
1928  if (!kind_info->from_serialized_name)
1929  {
1930  elog(WARNING, "invalid from_serialized_name in stats kind %u for entry of type %c",
1931  kind, t);
1932  goto error;
1933  }
1934 
1935  if (!kind_info->from_serialized_name(&name, &key))
1936  {
1937  /* skip over data for entry we don't care about */
1938  if (fseek(fpin, pgstat_get_entry_len(kind), SEEK_CUR) != 0)
1939  {
1940  elog(WARNING, "could not seek \"%s\" of stats kind %u for entry of type %c",
1941  NameStr(name), kind, t);
1942  goto error;
1943  }
1944 
1945  continue;
1946  }
1947 
1948  Assert(key.kind == kind);
1949  }
1950 
1951  /*
1952  * This intentionally doesn't use pgstat_get_entry_ref() -
1953  * putting all stats into checkpointer's
1954  * pgStatEntryRefHash would be wasted effort and memory.
1955  */
1957 
1958  /* don't allow duplicate entries */
1959  if (found)
1960  {
1962  elog(WARNING, "found duplicate stats entry %u/%u/%llu of type %c",
1963  key.kind, key.dboid,
1964  (unsigned long long) key.objid, t);
1965  goto error;
1966  }
1967 
1968  header = pgstat_init_entry(key.kind, p);
1970 
1971  if (!read_chunk(fpin,
1972  pgstat_get_entry_data(key.kind, header),
1973  pgstat_get_entry_len(key.kind)))
1974  {
1975  elog(WARNING, "could not read data for entry %u/%u/%llu of type %c",
1976  key.kind, key.dboid,
1977  (unsigned long long) key.objid, t);
1978  goto error;
1979  }
1980 
1981  break;
1982  }
1983  case PGSTAT_FILE_ENTRY_END:
1984 
1985  /*
1986  * check that PGSTAT_FILE_ENTRY_END actually signals end of
1987  * file
1988  */
1989  if (fgetc(fpin) != EOF)
1990  {
1991  elog(WARNING, "could not read end-of-file");
1992  goto error;
1993  }
1994 
1995  goto done;
1996 
1997  default:
1998  elog(WARNING, "could not read entry of type %c", t);
1999  goto error;
2000  }
2001  }
2002 
2003 done:
2004  FreeFile(fpin);
2005 
2006  elog(DEBUG2, "removing permanent stats file \"%s\"", statfile);
2007  unlink(statfile);
2008 
2009  return;
2010 
2011 error:
2012  ereport(LOG,
2013  (errmsg("corrupted statistics file \"%s\"", statfile)));
2014 
2016 
2017  goto done;
#define NameStr(name)
Definition: c.h:737
#define PG_BINARY_R
Definition: c.h:1266
signed int int32
Definition: c.h:496
void dshash_release_lock(dshash_table *hash_table, void *entry)
Definition: dshash.c:558
void * dshash_find_or_insert(dshash_table *hash_table, const void *key, bool *found)
Definition: dshash.c:433
#define WARNING
Definition: elog.h:36
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2606
int FreeFile(FILE *file)
Definition: fd.c:2804
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:122
#define PGSTAT_FILE_ENTRY_END
Definition: pgstat.c:143
static bool pgstat_is_kind_valid(PgStat_Kind kind)
Definition: pgstat.c:1424
#define PGSTAT_FILE_ENTRY_HASH
Definition: pgstat.c:146
#define PGSTAT_FILE_ENTRY_FIXED
Definition: pgstat.c:144
static bool read_chunk(FILE *fpin, void *ptr, size_t len)
Definition: pgstat.c:1721
#define read_chunk_s(fpin, ptr)
Definition: pgstat.c:1726
#define PGSTAT_FILE_ENTRY_NAME
Definition: pgstat.c:145
#define PGSTAT_FILE_FORMAT_ID
Definition: pgstat.h:270
static size_t pgstat_get_entry_len(PgStat_Kind kind)
PgStatShared_Common * pgstat_init_entry(PgStat_Kind kind, PgStatShared_HashEntry *shhashent)
Definition: pgstat_shmem.c:293
static void error(void)
Definition: sql-dyntest.c:147
bool(* from_serialized_name)(const NameData *name, PgStat_HashKey *key)
void * custom_data[PGSTAT_KIND_CUSTOM_SIZE]
Definition: c.h:732
#define LSN_FORMAT_ARGS(lsn)
Definition: xlogdefs.h:43
uint64 XLogRecPtr
Definition: xlogdefs.h:21

References AllocateFile(), Assert, CHECK_FOR_INTERRUPTS, PgStat_ShmemControl::custom_data, DEBUG2, dshash_find_or_insert(), dshash_release_lock(), elog, ereport, errcode_for_file_access(), errmsg(), error(), PgStat_KindInfo::fixed_amount, FreeFile(), PgStat_KindInfo::from_serialized_name, idx(), IsPostmasterEnvironment, IsUnderPostmaster, sort-test::key, LOG, LSN_FORMAT_ARGS, name, NameStr, PG_BINARY_R, PGSTAT_FILE_ENTRY_END, PGSTAT_FILE_ENTRY_FIXED, PGSTAT_FILE_ENTRY_HASH, PGSTAT_FILE_ENTRY_NAME, PGSTAT_FILE_FORMAT_ID, pgstat_get_entry_data(), pgstat_get_entry_len(), pgstat_get_kind_info(), pgstat_init_entry(), pgstat_is_kind_builtin(), pgstat_is_kind_valid(), PgStat_Kind, PGSTAT_KIND_CUSTOM_MIN, pgstat_reset_after_failure(), PGSTAT_STAT_PERMANENT_FILENAME, pgStatLocal, read_chunk(), read_chunk_s, PgStat_KindInfo::shared_ctl_off, PgStat_KindInfo::shared_data_len, PgStat_KindInfo::shared_data_off, PgStat_LocalState::shared_hash, PgStat_LocalState::shmem, and WARNING.

Referenced by pgstat_restore_stats().

◆ pgstat_register_kind()

void pgstat_register_kind ( PgStat_Kind  kind,
const PgStat_KindInfo kind_info 
)

Definition at line 1458 of file pgstat.c.

1460 {
1462 
1463  if (kind_info->name == NULL || strlen(kind_info->name) == 0)
1464  ereport(ERROR,
1465  (errmsg("custom cumulative statistics name is invalid"),
1466  errhint("Provide a non-empty name for the custom cumulative statistics.")));
1467 
1468  if (!pgstat_is_kind_custom(kind))
1469  ereport(ERROR, (errmsg("custom cumulative statistics ID %u is out of range", kind),
1470  errhint("Provide a custom cumulative statistics ID between %u and %u.",
1472 
1474  ereport(ERROR,
1475  (errmsg("failed to register custom cumulative statistics \"%s\" with ID %u", kind_info->name, kind),
1476  errdetail("Custom cumulative statistics must be registered while initializing modules in \"shared_preload_libraries\".")));
1477 
1478  /*
1479  * Check some data for fixed-numbered stats.
1480  */
1481  if (kind_info->fixed_amount)
1482  {
1483  if (kind_info->shared_size == 0)
1484  ereport(ERROR,
1485  (errmsg("custom cumulative statistics property is invalid"),
1486  errhint("Custom cumulative statistics require a shared memory size for fixed-numbered objects.")));
1487  }
1488 
1489  /*
1490  * If pgstat_kind_custom_infos is not available yet, allocate it.
1491  */
1492  if (pgstat_kind_custom_infos == NULL)
1493  {
1497  }
1498 
1499  if (pgstat_kind_custom_infos[idx] != NULL &&
1500  pgstat_kind_custom_infos[idx]->name != NULL)
1501  ereport(ERROR,
1502  (errmsg("failed to register custom cumulative statistics \"%s\" with ID %u", kind_info->name, kind),
1503  errdetail("Custom cumulative statistics \"%s\" already registered with the same ID.",
1505 
1506  /* check for existing custom stats with the same name */
1507  for (PgStat_Kind existing_kind = PGSTAT_KIND_CUSTOM_MIN; existing_kind <= PGSTAT_KIND_CUSTOM_MAX; existing_kind++)
1508  {
1509  uint32 existing_idx = existing_kind - PGSTAT_KIND_CUSTOM_MIN;
1510 
1511  if (pgstat_kind_custom_infos[existing_idx] == NULL)
1512  continue;
1513  if (!pg_strcasecmp(pgstat_kind_custom_infos[existing_idx]->name, kind_info->name))
1514  ereport(ERROR,
1515  (errmsg("failed to register custom cumulative statistics \"%s\" with ID %u", kind_info->name, kind),
1516  errdetail("Existing cumulative statistics with ID %u has the same name.", existing_kind)));
1517  }
1518 
1519  /* Register it */
1520  pgstat_kind_custom_infos[idx] = kind_info;
1521  ereport(LOG,
1522  (errmsg("registered custom cumulative statistics \"%s\" with ID %u",
1523  kind_info->name, kind)));
int errdetail(const char *fmt,...)
Definition: elog.c:1203
int errhint(const char *fmt,...)
Definition: elog.c:1317
bool process_shared_preload_libraries_in_progress
Definition: miscinit.c:1778
#define PGSTAT_KIND_CUSTOM_SIZE
Definition: pgstat.h:70
const char *const name

References ereport, errdetail(), errhint(), errmsg(), ERROR, PgStat_KindInfo::fixed_amount, idx(), LOG, MemoryContextAllocZero(), name, PgStat_KindInfo::name, pg_strcasecmp(), pgstat_is_kind_custom(), PgStat_Kind, pgstat_kind_custom_infos, PGSTAT_KIND_CUSTOM_MAX, PGSTAT_KIND_CUSTOM_MIN, PGSTAT_KIND_CUSTOM_SIZE, process_shared_preload_libraries_in_progress, PgStat_KindInfo::shared_size, and TopMemoryContext.

Referenced by pgstat_register_inj(), and pgstat_register_inj_fixed().

◆ pgstat_report_stat()

long pgstat_report_stat ( bool  force)

Definition at line 660 of file pgstat.c.

662 {
663  static TimestampTz pending_since = 0;
664  static TimestampTz last_flush = 0;
665  bool partial_flush;
667  bool nowait;
668 
671 
672  /* "absorb" the forced flush even if there's nothing to flush */
674  {
675  force = true;
676  pgStatForceNextFlush = false;
677  }
678 
679  /* Don't expend a clock check if nothing to do */
681  {
682  bool do_flush = false;
683 
684  /* Check for pending fixed-numbered stats */
685  for (PgStat_Kind kind = PGSTAT_KIND_MIN; kind <= PGSTAT_KIND_MAX; kind++)
686  {
687  const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind);
688 
689  if (!kind_info)
690  continue;
691  if (!kind_info->fixed_amount)
692  {
693  Assert(kind_info->have_fixed_pending_cb == NULL);
694  continue;
695  }
696  if (!kind_info->have_fixed_pending_cb)
697  continue;
698 
699  if (kind_info->have_fixed_pending_cb())
700  {
701  do_flush = true;
702  break;
703  }
704  }
705 
706  if (!do_flush)
707  {
708  Assert(pending_since == 0);
709  return 0;
710  }
711  }
712 
713  /*
714  * There should never be stats to report once stats are shut down. Can't
715  * assert that before the checks above, as there is an unconditional
716  * pgstat_report_stat() call in pgstat_shutdown_hook() - which at least
717  * the process that ran pgstat_before_server_shutdown() will still call.
718  */
720 
721  if (force)
722  {
723  /*
724  * Stats reports are forced either when it's been too long since stats
725  * have been reported or in processes that force stats reporting to
726  * happen at specific points (including shutdown). In the former case
727  * the transaction stop time might be quite old, in the latter it
728  * would never get cleared.
729  */
731  }
732  else
733  {
735 
736  if (pending_since > 0 &&
738  {
739  /* don't keep pending updates longer than PGSTAT_MAX_INTERVAL */
740  force = true;
741  }
742  else if (last_flush > 0 &&
744  {
745  /* don't flush too frequently */
746  if (pending_since == 0)
747  pending_since = now;
748 
749  return PGSTAT_IDLE_INTERVAL;
750  }
751  }
752 
754 
755  /* don't wait for lock acquisition when !force */
756  nowait = !force;
757 
758  partial_flush = false;
759 
760  /* flush database / relation / function / ... stats */
761  partial_flush |= pgstat_flush_pending_entries(nowait);
762 
763  /* flush of fixed-numbered stats */
764  for (PgStat_Kind kind = PGSTAT_KIND_MIN; kind <= PGSTAT_KIND_MAX; kind++)
765  {
766  const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind);
767 
768  if (!kind_info)
769  continue;
770  if (!kind_info->fixed_amount)
771  {
772  Assert(kind_info->flush_fixed_cb == NULL);
773  continue;
774  }
775  if (!kind_info->flush_fixed_cb)
776  continue;
777 
778  partial_flush |= kind_info->flush_fixed_cb(nowait);
779  }
780 
781  last_flush = now;
782 
783  /*
784  * If some of the pending stats could not be flushed due to lock
785  * contention, let the caller know when to retry.
786  */
787  if (partial_flush)
788  {
789  /* force should have prevented us from getting here */
790  Assert(!force);
791 
792  /* remember since when stats have been pending */
793  if (pending_since == 0)
794  pending_since = now;
795 
796  return PGSTAT_IDLE_INTERVAL;
797  }
798 
799  pending_since = 0;
800 
801  return 0;
bool TimestampDifferenceExceeds(TimestampTz start_time, TimestampTz stop_time, int msec)
Definition: timestamp.c:1780
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1608
int64 TimestampTz
Definition: timestamp.h:39
#define PGSTAT_MIN_INTERVAL
Definition: pgstat.c:126
static bool pgstat_flush_pending_entries(bool nowait)
Definition: pgstat.c:1334
#define PGSTAT_MAX_INTERVAL
Definition: pgstat.c:128
#define PGSTAT_IDLE_INTERVAL
Definition: pgstat.c:130
void pgstat_update_dbstats(TimestampTz ts)
bool(* have_fixed_pending_cb)(void)
bool(* flush_fixed_cb)(bool nowait)
bool IsTransactionOrTransactionBlock(void)
Definition: xact.c:4982
TimestampTz GetCurrentTransactionStopTimestamp(void)
Definition: xact.c:890

References Assert, dlist_is_empty(), PgStat_KindInfo::fixed_amount, PgStat_KindInfo::flush_fixed_cb, GetCurrentTimestamp(), GetCurrentTransactionStopTimestamp(), PgStat_KindInfo::have_fixed_pending_cb, PgStat_ShmemControl::is_shutdown, IsTransactionOrTransactionBlock(), now(), pgstat_assert_is_up, pgstat_flush_pending_entries(), pgstat_get_kind_info(), PGSTAT_IDLE_INTERVAL, PgStat_Kind, PGSTAT_KIND_MAX, PGSTAT_KIND_MIN, PGSTAT_MAX_INTERVAL, PGSTAT_MIN_INTERVAL, pgstat_update_dbstats(), pgStatForceNextFlush, pgStatLocal, pgStatPending, PgStat_LocalState::shmem, and TimestampDifferenceExceeds().

Referenced by AllTablesyncsReady(), apply_handle_commit_internal(), apply_handle_commit_prepared(), apply_handle_prepare(), apply_handle_rollback_prepared(), apply_handle_stream_prepare(), LogicalRepApplyLoop(), LogicalRepSyncTableStart(), pg_attribute_noreturn(), pgstat_before_server_shutdown(), pgstat_shutdown_hook(), PostgresMain(), process_syncing_tables_for_apply(), process_syncing_tables_for_sync(), ProcessInterrupts(), standby_redo(), and worker_spi_main().

◆ pgstat_reset()

void pgstat_reset ( PgStat_Kind  kind,
Oid  dboid,
uint64  objid 
)

Definition at line 848 of file pgstat.c.

850 {
851  const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind);
853 
854  /* not needed atm, and doesn't make sense with the current signature */
855  Assert(!pgstat_get_kind_info(kind)->fixed_amount);
856 
857  /* reset the "single counter" */
858  pgstat_reset_entry(kind, dboid, objid, ts);
859 
860  if (!kind_info->accessed_across_databases)
void pgstat_reset_database_timestamp(Oid dboid, TimestampTz ts)
void pgstat_reset_entry(PgStat_Kind kind, Oid dboid, uint64 objid, TimestampTz ts)
Definition: pgstat_shmem.c:984

References PgStat_KindInfo::accessed_across_databases, Assert, GetCurrentTimestamp(), pgstat_get_kind_info(), pgstat_reset_database_timestamp(), and pgstat_reset_entry().

Referenced by pg_stat_reset_single_function_counters(), pg_stat_reset_single_table_counters(), pg_stat_reset_subscription_stats(), pgstat_create_transactional(), and pgstat_reset_replslot().

◆ pgstat_reset_after_failure()

static void pgstat_reset_after_failure ( void  )
static

Definition at line 2024 of file pgstat.c.

2026 {
2028 
2029  /* reset fixed-numbered stats */
2030  for (PgStat_Kind kind = PGSTAT_KIND_MIN; kind <= PGSTAT_KIND_MAX; kind++)
2031  {
2032  const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind);
2033 
2034  if (!kind_info || !kind_info->fixed_amount)
2035  continue;
2036 
2037  kind_info->reset_all_cb(ts);
2038  }
2039 
2040  /* and drop variable-numbered ones */
void pgstat_drop_all_entries(void)
Definition: pgstat_shmem.c:946
void(* reset_all_cb)(TimestampTz ts)

References PgStat_KindInfo::fixed_amount, GetCurrentTimestamp(), pgstat_drop_all_entries(), pgstat_get_kind_info(), PgStat_Kind, PGSTAT_KIND_MAX, PGSTAT_KIND_MIN, and PgStat_KindInfo::reset_all_cb.

Referenced by pgstat_discard_stats(), and pgstat_read_statsfile().

◆ pgstat_reset_counters()

void pgstat_reset_counters ( void  )

Definition at line 829 of file pgstat.c.

831 {
833 
836  ts);
static bool match_db_entries(PgStatShared_HashEntry *entry, Datum match_data)
Definition: pgstat.c:817
void pgstat_reset_matching_entries(bool(*do_reset)(PgStatShared_HashEntry *, Datum), Datum match_data, TimestampTz ts)
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252

References GetCurrentTimestamp(), match_db_entries(), MyDatabaseId, ObjectIdGetDatum(), and pgstat_reset_matching_entries().

Referenced by pg_stat_reset().

◆ pgstat_reset_of_kind()

void pgstat_reset_of_kind ( PgStat_Kind  kind)

Definition at line 870 of file pgstat.c.

872 {
873  const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind);
875 
876  if (kind_info->fixed_amount)
877  kind_info->reset_all_cb(ts);
878  else
void pgstat_reset_entries_of_kind(PgStat_Kind kind, TimestampTz ts)

References PgStat_KindInfo::fixed_amount, GetCurrentTimestamp(), pgstat_get_kind_info(), pgstat_reset_entries_of_kind(), and PgStat_KindInfo::reset_all_cb.

Referenced by pg_stat_reset_replication_slot(), pg_stat_reset_shared(), pg_stat_reset_slru(), and pg_stat_reset_subscription_stats().

◆ pgstat_restore_stats()

void pgstat_restore_stats ( XLogRecPtr  redo)

Definition at line 477 of file pgstat.c.

479 {
480  pgstat_read_statsfile(redo);
static void pgstat_read_statsfile(XLogRecPtr redo)
Definition: pgstat.c:1735

References pgstat_read_statsfile().

Referenced by StartupXLOG().

◆ pgstat_shutdown_hook()

static void pgstat_shutdown_hook ( int  code,
Datum  arg 
)
static

Definition at line 573 of file pgstat.c.

575 {
576  Assert(!pgstat_is_shutdown);
578 
579  /*
580  * If we got as far as discovering our own database ID, we can flush out
581  * what we did so far. Otherwise, we'd be reporting an invalid database
582  * ID, so forget it. (This means that accesses to pg_database during
583  * failed backend starts might never get counted.)
584  */
587 
588  pgstat_report_stat(true);
589 
590  /* there shouldn't be any pending changes left */
593 
595 
596 #ifdef USE_ASSERT_CHECKING
597  pgstat_is_shutdown = true;
598 #endif
#define OidIsValid(objectId)
Definition: c.h:766
static void dlist_init(dlist_head *head)
Definition: ilist.h:314
void pgstat_report_disconnect(Oid dboid)
void pgstat_detach_shmem(void)
Definition: pgstat_shmem.c:264

References Assert, dlist_init(), dlist_is_empty(), IsPostmasterEnvironment, IsUnderPostmaster, MyDatabaseId, OidIsValid, pgstat_detach_shmem(), pgstat_report_disconnect(), pgstat_report_stat(), and pgStatPending.

Referenced by pgstat_initialize().

◆ pgstat_snapshot_fixed()

◆ pgstat_write_statsfile()

static void pgstat_write_statsfile ( XLogRecPtr  redo)
static

Definition at line 1563 of file pgstat.c.

1565 {
1566  FILE *fpout;
1567  int32 format_id;
1568  const char *tmpfile = PGSTAT_STAT_PERMANENT_TMPFILE;
1569  const char *statfile = PGSTAT_STAT_PERMANENT_FILENAME;
1570  dshash_seq_status hstat;
1572 
1574 
1575  /* should be called only by the checkpointer or single user mode */
1577 
1578  /* we're shutting down, so it's ok to just override this */
1580 
1581  elog(DEBUG2, "writing stats file \"%s\" with redo %X/%X", statfile,
1582  LSN_FORMAT_ARGS(redo));
1583 
1584  /*
1585  * Open the statistics temp file to write out the current values.
1586  */
1587  fpout = AllocateFile(tmpfile, PG_BINARY_W);
1588  if (fpout == NULL)
1589  {
1590  ereport(LOG,
1592  errmsg("could not open temporary statistics file \"%s\": %m",
1593  tmpfile)));
1594  return;
1595  }
1596 
1597  /*
1598  * Write the file header --- currently just a format ID.
1599  */
1600  format_id = PGSTAT_FILE_FORMAT_ID;
1601  write_chunk_s(fpout, &format_id);
1602 
1603  /* Write the redo LSN, used to cross check the file read */
1604  write_chunk_s(fpout, &redo);
1605 
1606  /* Write various stats structs for fixed number of objects */
1607  for (PgStat_Kind kind = PGSTAT_KIND_MIN; kind <= PGSTAT_KIND_MAX; kind++)
1608  {
1609  char *ptr;
1610  const PgStat_KindInfo *info = pgstat_get_kind_info(kind);
1611 
1612  if (!info || !info->fixed_amount)
1613  continue;
1614 
1615  if (pgstat_is_kind_builtin(kind))
1616  Assert(info->snapshot_ctl_off != 0);
1617 
1619  if (pgstat_is_kind_builtin(kind))
1620  ptr = ((char *) &pgStatLocal.snapshot) + info->snapshot_ctl_off;
1621  else
1623 
1624  fputc(PGSTAT_FILE_ENTRY_FIXED, fpout);
1625  write_chunk_s(fpout, &kind);
1626  write_chunk(fpout, ptr, info->shared_data_len);
1627  }
1628 
1629  /*
1630  * Walk through the stats entries
1631  */
1632  dshash_seq_init(&hstat, pgStatLocal.shared_hash, false);
1633  while ((ps = dshash_seq_next(&hstat)) != NULL)
1634  {
1635  PgStatShared_Common *shstats;
1636  const PgStat_KindInfo *kind_info = NULL;
1637 
1639 
1640  /* we may have some "dropped" entries not yet removed, skip them */
1641  Assert(!ps->dropped);
1642  if (ps->dropped)
1643  continue;
1644 
1645  /*
1646  * This discards data related to custom stats kinds that are unknown
1647  * to this process.
1648  */
1649  if (!pgstat_is_kind_valid(ps->key.kind))
1650  {
1651  elog(WARNING, "found unknown stats entry %u/%u/%llu",
1652  ps->key.kind, ps->key.dboid,
1653  (unsigned long long) ps->key.objid);
1654  continue;
1655  }
1656 
1657  shstats = (PgStatShared_Common *) dsa_get_address(pgStatLocal.dsa, ps->body);
1658 
1659  kind_info = pgstat_get_kind_info(ps->key.kind);
1660 
1661  /* if not dropped the valid-entry refcount should exist */
1662  Assert(pg_atomic_read_u32(&ps->refcount) > 0);
1663 
1664  if (!kind_info->to_serialized_name)
1665  {
1666  /* normal stats entry, identified by PgStat_HashKey */
1667  fputc(PGSTAT_FILE_ENTRY_HASH, fpout);
1668  write_chunk_s(fpout, &ps->key);
1669  }
1670  else
1671  {
1672  /* stats entry identified by name on disk (e.g. slots) */
1673  NameData name;
1674 
1675  kind_info->to_serialized_name(&ps->key, shstats, &name);
1676 
1677  fputc(PGSTAT_FILE_ENTRY_NAME, fpout);
1678  write_chunk_s(fpout, &ps->key.kind);
1679  write_chunk_s(fpout, &name);
1680  }
1681 
1682  /* Write except the header part of the entry */
1683  write_chunk(fpout,
1684  pgstat_get_entry_data(ps->key.kind, shstats),
1685  pgstat_get_entry_len(ps->key.kind));
1686  }
1687  dshash_seq_term(&hstat);
1688 
1689  /*
1690  * No more output to be done. Close the temp file and replace the old
1691  * pgstat.stat with it. The ferror() check replaces testing for error
1692  * after each individual fputc or fwrite (in write_chunk()) above.
1693  */
1694  fputc(PGSTAT_FILE_ENTRY_END, fpout);
1695 
1696  if (ferror(fpout))
1697  {
1698  ereport(LOG,
1700  errmsg("could not write temporary statistics file \"%s\": %m",
1701  tmpfile)));
1702  FreeFile(fpout);
1703  unlink(tmpfile);
1704  }
1705  else if (FreeFile(fpout) < 0)
1706  {
1707  ereport(LOG,
1709  errmsg("could not close temporary statistics file \"%s\": %m",
1710  tmpfile)));
1711  unlink(tmpfile);
1712  }
1713  else if (durable_rename(tmpfile, statfile, LOG) < 0)
1714  {
1715  /* durable_rename already emitted log message */
1716  unlink(tmpfile);
1717  }
#define PG_BINARY_W
Definition: c.h:1267
int durable_rename(const char *oldfile, const char *newfile, int elevel)
Definition: fd.c:782
struct parser_state ps
@ B_CHECKPOINTER
Definition: miscadmin.h:354
BackendType MyBackendType
Definition: miscinit.c:63
static void write_chunk(FILE *fpout, void *ptr, size_t len)
Definition: pgstat.c:1546
#define write_chunk_s(fpout, ptr)
Definition: pgstat.c:1556
#define PGSTAT_STAT_PERMANENT_TMPFILE
Definition: pgstat.h:31
void(* to_serialized_name)(const PgStat_HashKey *key, const PgStatShared_Common *header, NameData *name)

References AllocateFile(), Assert, B_CHECKPOINTER, CHECK_FOR_INTERRUPTS, PgStat_Snapshot::custom_data, DEBUG2, PgStat_LocalState::dsa, dsa_get_address(), dshash_seq_init(), dshash_seq_next(), dshash_seq_term(), durable_rename(), elog, ereport, errcode_for_file_access(), errmsg(), PgStat_KindInfo::fixed_amount, FreeFile(), IsUnderPostmaster, LOG, LSN_FORMAT_ARGS, MyBackendType, name, pg_atomic_read_u32(), PG_BINARY_W, pgstat_assert_is_up, pgstat_build_snapshot_fixed(), pgstat_fetch_consistency, PGSTAT_FETCH_CONSISTENCY_NONE, PGSTAT_FILE_ENTRY_END, PGSTAT_FILE_ENTRY_FIXED, PGSTAT_FILE_ENTRY_HASH, PGSTAT_FILE_ENTRY_NAME, PGSTAT_FILE_FORMAT_ID, pgstat_get_entry_data(), pgstat_get_entry_len(), pgstat_get_kind_info(), pgstat_is_kind_builtin(), pgstat_is_kind_valid(), PgStat_Kind, PGSTAT_KIND_CUSTOM_MIN, PGSTAT_KIND_MAX, PGSTAT_KIND_MIN, PGSTAT_STAT_PERMANENT_FILENAME, PGSTAT_STAT_PERMANENT_TMPFILE, pgStatLocal, ps, PgStat_KindInfo::shared_data_len, PgStat_LocalState::shared_hash, PgStat_LocalState::snapshot, PgStat_KindInfo::snapshot_ctl_off, PgStat_KindInfo::to_serialized_name, WARNING, write_chunk(), and write_chunk_s.

Referenced by pgstat_before_server_shutdown().

◆ read_chunk()

static bool read_chunk ( FILE *  fpin,
void *  ptr,
size_t  len 
)
static

Definition at line 1721 of file pgstat.c.

1723 {
1724  return fread(ptr, 1, len, fpin) == len;
const void size_t len

References len.

Referenced by pgstat_read_statsfile().

◆ write_chunk()

static void write_chunk ( FILE *  fpout,
void *  ptr,
size_t  len 
)
static

Definition at line 1546 of file pgstat.c.

1548 {
1549  int rc;
1550 
1551  rc = fwrite(ptr, len, 1, fpout);
1552 
1553  /* we'll check for errors with ferror once at the end */
1554  (void) rc;

References len.

Referenced by pgstat_write_statsfile().

Variable Documentation

◆ force_stats_snapshot_clear

◆ pgstat_fetch_consistency

◆ pgstat_kind_builtin_infos

const PgStat_KindInfo pgstat_kind_builtin_infos[PGSTAT_KIND_BUILTIN_SIZE]
static

Definition at line 276 of file pgstat.c.

Referenced by pgstat_get_kind_from_str(), and pgstat_get_kind_info().

◆ pgstat_kind_custom_infos

const PgStat_KindInfo** pgstat_kind_custom_infos = NULL
static

Definition at line 464 of file pgstat.c.

Referenced by pgstat_get_kind_from_str(), pgstat_get_kind_info(), and pgstat_register_kind().

◆ pgstat_track_counts

◆ pgStatForceNextFlush

bool pgStatForceNextFlush = false
static

Definition at line 244 of file pgstat.c.

Referenced by pgstat_force_next_flush(), and pgstat_report_stat().

◆ pgStatLocal

PgStat_LocalState pgStatLocal

Definition at line 212 of file pgstat.c.

Referenced by pgstat_acquire_entry_ref(), pgstat_archiver_reset_all_cb(), pgstat_archiver_snapshot_cb(), pgstat_attach_shmem(), pgstat_before_server_shutdown(), pgstat_bgwriter_reset_all_cb(), pgstat_bgwriter_snapshot_cb(), pgstat_build_snapshot(), pgstat_build_snapshot_fixed(), pgstat_checkpointer_reset_all_cb(), pgstat_checkpointer_snapshot_cb(), pgstat_clear_snapshot(), pgstat_detach_shmem(), pgstat_drop_all_entries(), pgstat_drop_database_and_contents(), pgstat_drop_entry(), pgstat_drop_entry_internal(), pgstat_fetch_entry(), pgstat_fetch_slru(), pgstat_fetch_stat_archiver(), pgstat_fetch_stat_bgwriter(), pgstat_fetch_stat_checkpointer(), pgstat_fetch_stat_io(), pgstat_fetch_stat_wal(), pgstat_free_entry(), pgstat_gc_entry_refs(), pgstat_get_custom_shmem_data(), pgstat_get_custom_snapshot_data(), pgstat_get_entry_ref(), pgstat_get_stat_snapshot_timestamp(), pgstat_init_entry(), pgstat_init_snapshot_fixed(), pgstat_io_flush_cb(), pgstat_io_reset_all_cb(), pgstat_io_snapshot_cb(), pgstat_need_entry_refs_gc(), pgstat_prep_snapshot(), pgstat_read_statsfile(), pgstat_reinit_entry(), pgstat_release_entry_ref(), pgstat_report_archiver(), pgstat_report_bgwriter(), pgstat_report_checkpointer(), pgstat_report_stat(), pgstat_request_entry_refs_gc(), pgstat_reset_matching_entries(), pgstat_reset_slru_counter_internal(), pgstat_setup_shared_refs(), pgstat_slru_flush_cb(), pgstat_slru_snapshot_cb(), pgstat_snapshot_fixed(), pgstat_wal_flush_cb(), pgstat_wal_reset_all_cb(), pgstat_wal_snapshot_cb(), pgstat_write_statsfile(), and StatsShmemInit().

◆ pgStatPending

dlist_head pgStatPending = DLIST_STATIC_INIT(pgStatPending)
static

◆ pgStatPendingContext

MemoryContext pgStatPendingContext = NULL
static

Definition at line 229 of file pgstat.c.

Referenced by pgstat_prep_pending_entry().