Thanks to visit codestin.com
Credit goes to doxygen.postgresql.org

PostgreSQL Source Code git master
pgstat_shmem.c File Reference
#include "postgres.h"
#include "pgstat.h"
#include "storage/shmem.h"
#include "utils/memutils.h"
#include "utils/pgstat_internal.h"
#include "lib/simplehash.h"
Include dependency graph for pgstat_shmem.c:

Go to the source code of this file.

Data Structures

struct  PgStat_EntryRefHashEntry
 

Macros

#define PGSTAT_ENTRY_REF_HASH_SIZE   128
 
#define SH_PREFIX   pgstat_entry_ref_hash
 
#define SH_ELEMENT_TYPE   PgStat_EntryRefHashEntry
 
#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
 

Typedefs

typedef struct PgStat_EntryRefHashEntry PgStat_EntryRefHashEntry
 
typedef bool(* ReleaseMatchCB) (PgStat_EntryRefHashEntry *, Datum data)
 

Functions

static void pgstat_drop_database_and_contents (Oid dboid)
 
static void pgstat_free_entry (PgStatShared_HashEntry *shent, dshash_seq_status *hstat)
 
static void pgstat_release_entry_ref (PgStat_HashKey key, PgStat_EntryRef *entry_ref, bool discard_pending)
 
static bool pgstat_need_entry_refs_gc (void)
 
static void pgstat_gc_entry_refs (void)
 
static void pgstat_release_all_entry_refs (bool discard_pending)
 
static void pgstat_release_matching_entry_refs (bool discard_pending, ReleaseMatchCB match, Datum match_data)
 
static void pgstat_setup_memcxt (void)
 
static Size pgstat_dsa_init_size (void)
 
Size StatsShmemSize (void)
 
void StatsShmemInit (void)
 
void pgstat_attach_shmem (void)
 
void pgstat_detach_shmem (void)
 
PgStatShared_Commonpgstat_init_entry (PgStat_Kind kind, PgStatShared_HashEntry *shhashent)
 
static PgStatShared_Commonpgstat_reinit_entry (PgStat_Kind kind, PgStatShared_HashEntry *shhashent)
 
static void pgstat_setup_shared_refs (void)
 
static void pgstat_acquire_entry_ref (PgStat_EntryRef *entry_ref, PgStatShared_HashEntry *shhashent, PgStatShared_Common *shheader)
 
static bool pgstat_get_entry_ref_cached (PgStat_HashKey key, PgStat_EntryRef **entry_ref_p)
 
PgStat_EntryRefpgstat_get_entry_ref (PgStat_Kind kind, Oid dboid, uint64 objid, bool create, bool *created_entry)
 
bool pgstat_lock_entry (PgStat_EntryRef *entry_ref, bool nowait)
 
bool pgstat_lock_entry_shared (PgStat_EntryRef *entry_ref, bool nowait)
 
void pgstat_unlock_entry (PgStat_EntryRef *entry_ref)
 
PgStat_EntryRefpgstat_get_entry_ref_locked (PgStat_Kind kind, Oid dboid, uint64 objid, bool nowait)
 
void pgstat_request_entry_refs_gc (void)
 
static bool match_db (PgStat_EntryRefHashEntry *ent, Datum match_data)
 
static void pgstat_release_db_entry_refs (Oid dboid)
 
static bool pgstat_drop_entry_internal (PgStatShared_HashEntry *shent, dshash_seq_status *hstat)
 
bool pgstat_drop_entry (PgStat_Kind kind, Oid dboid, uint64 objid)
 
void pgstat_drop_matching_entries (bool(*do_drop)(PgStatShared_HashEntry *, Datum), Datum match_data)
 
void pgstat_drop_all_entries (void)
 
static void shared_stat_reset_contents (PgStat_Kind kind, PgStatShared_Common *header, TimestampTz ts)
 
void pgstat_reset_entry (PgStat_Kind kind, Oid dboid, uint64 objid, TimestampTz ts)
 
void pgstat_reset_matching_entries (bool(*do_reset)(PgStatShared_HashEntry *, Datum), Datum match_data, TimestampTz ts)
 
static bool match_kind (PgStatShared_HashEntry *p, Datum match_data)
 
void pgstat_reset_entries_of_kind (PgStat_Kind kind, TimestampTz ts)
 

Variables

static const dshash_parameters dsh_params
 
static pgstat_entry_ref_hash_hash * pgStatEntryRefHash = NULL
 
static int pgStatSharedRefAge = 0
 
static MemoryContext pgStatSharedRefContext = NULL
 
static MemoryContext pgStatEntryRefHashContext = NULL
 

Macro Definition Documentation

◆ PGSTAT_ENTRY_REF_HASH_SIZE

#define PGSTAT_ENTRY_REF_HASH_SIZE   128

Definition at line 21 of file pgstat_shmem.c.

◆ SH_DECLARE

#define SH_DECLARE

Definition at line 43 of file pgstat_shmem.c.

◆ SH_DEFINE

#define SH_DEFINE

Definition at line 42 of file pgstat_shmem.c.

◆ SH_ELEMENT_TYPE

#define SH_ELEMENT_TYPE   PgStat_EntryRefHashEntry

Definition at line 34 of file pgstat_shmem.c.

◆ SH_EQUAL

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

Definition at line 39 of file pgstat_shmem.c.

◆ SH_HASH_KEY

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

Definition at line 37 of file pgstat_shmem.c.

◆ SH_KEY

#define SH_KEY   key

Definition at line 36 of file pgstat_shmem.c.

◆ SH_KEY_TYPE

#define SH_KEY_TYPE   PgStat_HashKey

Definition at line 35 of file pgstat_shmem.c.

◆ SH_PREFIX

#define SH_PREFIX   pgstat_entry_ref_hash

Definition at line 33 of file pgstat_shmem.c.

◆ SH_SCOPE

#define SH_SCOPE   static inline

Definition at line 41 of file pgstat_shmem.c.

Typedef Documentation

◆ PgStat_EntryRefHashEntry

◆ ReleaseMatchCB

typedef bool(* ReleaseMatchCB) (PgStat_EntryRefHashEntry *, Datum data)

Definition at line 55 of file pgstat_shmem.c.

Function Documentation

◆ match_db()

static bool match_db ( PgStat_EntryRefHashEntry ent,
Datum  match_data 
)
static

Definition at line 850 of file pgstat_shmem.c.

851{
852 Oid dboid = DatumGetObjectId(match_data);
853
854 return ent->key.dboid == dboid;
855}
static Oid DatumGetObjectId(Datum X)
Definition: postgres.h:252
unsigned int Oid
Definition: postgres_ext.h:32

References DatumGetObjectId(), PgStat_HashKey::dboid, and PgStat_EntryRefHashEntry::key.

Referenced by pgstat_release_db_entry_refs().

◆ match_kind()

static bool match_kind ( PgStatShared_HashEntry p,
Datum  match_data 
)
static

Definition at line 1162 of file pgstat_shmem.c.

1163{
1164 return p->key.kind == DatumGetInt32(match_data);
1165}
static int32 DatumGetInt32(Datum X)
Definition: postgres.h:212
PgStat_Kind kind

References DatumGetInt32(), PgStatShared_HashEntry::key, and PgStat_HashKey::kind.

Referenced by pgstat_reset_entries_of_kind().

◆ pgstat_acquire_entry_ref()

static void pgstat_acquire_entry_ref ( PgStat_EntryRef entry_ref,
PgStatShared_HashEntry shhashent,
PgStatShared_Common shheader 
)
static

Definition at line 393 of file pgstat_shmem.c.

396{
397 Assert(shheader->magic == 0xdeadbeef);
398 Assert(pg_atomic_read_u32(&shhashent->refcount) > 0);
399
400 pg_atomic_fetch_add_u32(&shhashent->refcount, 1);
401
403
404 entry_ref->shared_stats = shheader;
405 entry_ref->shared_entry = shhashent;
406 entry_ref->generation = pg_atomic_read_u32(&shhashent->generation);
407}
static uint32 pg_atomic_fetch_add_u32(volatile pg_atomic_uint32 *ptr, int32 add_)
Definition: atomics.h:364
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition: atomics.h:237
void dshash_release_lock(dshash_table *hash_table, void *entry)
Definition: dshash.c:558
Assert(PointerIsAligned(start, uint64))
PgStat_LocalState pgStatLocal
Definition: pgstat.c:212
pg_atomic_uint32 refcount
pg_atomic_uint32 generation
PgStatShared_Common * shared_stats
PgStatShared_HashEntry * shared_entry
dshash_table * shared_hash

References Assert(), dshash_release_lock(), PgStatShared_HashEntry::generation, PgStat_EntryRef::generation, PgStatShared_Common::magic, pg_atomic_fetch_add_u32(), pg_atomic_read_u32(), pgStatLocal, PgStatShared_HashEntry::refcount, PgStat_EntryRef::shared_entry, PgStat_LocalState::shared_hash, and PgStat_EntryRef::shared_stats.

Referenced by pgstat_get_entry_ref().

◆ pgstat_attach_shmem()

void pgstat_attach_shmem ( void  )

Definition at line 251 of file pgstat_shmem.c.

252{
253 MemoryContext oldcontext;
254
255 Assert(pgStatLocal.dsa == NULL);
256
257 /* stats shared memory persists for the backend lifetime */
259
261 NULL);
263
266 NULL);
267
268 MemoryContextSwitchTo(oldcontext);
269}
dsa_area * dsa_attach_in_place(void *place, dsm_segment *segment)
Definition: dsa.c:560
void dsa_pin_mapping(dsa_area *area)
Definition: dsa.c:650
dshash_table * dshash_attach(dsa_area *area, const dshash_parameters *params, dshash_table_handle handle, void *arg)
Definition: dshash.c:270
MemoryContext TopMemoryContext
Definition: mcxt.c:166
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
static const dshash_parameters dsh_params
Definition: pgstat_shmem.c:62
PgStat_ShmemControl * shmem
dshash_table_handle hash_handle

References Assert(), PgStat_LocalState::dsa, dsa_attach_in_place(), dsa_pin_mapping(), dsh_params, dshash_attach(), PgStat_ShmemControl::hash_handle, MemoryContextSwitchTo(), pgStatLocal, PgStat_ShmemControl::raw_dsa_area, PgStat_LocalState::shared_hash, PgStat_LocalState::shmem, and TopMemoryContext.

Referenced by pgstat_initialize().

◆ pgstat_detach_shmem()

void pgstat_detach_shmem ( void  )

Definition at line 272 of file pgstat_shmem.c.

273{
275
276 /* we shouldn't leave references to shared stats */
278
281
283
284 /*
285 * dsa_detach() does not decrement the DSA reference count as no segment
286 * was provided to dsa_attach_in_place(), causing no cleanup callbacks to
287 * be registered. Hence, release it manually now.
288 */
290
291 pgStatLocal.dsa = NULL;
292}
void dsa_release_in_place(void *place)
Definition: dsa.c:620
void dsa_detach(dsa_area *area)
Definition: dsa.c:1967
void dshash_detach(dshash_table *hash_table)
Definition: dshash.c:307
static void pgstat_release_all_entry_refs(bool discard_pending)
Definition: pgstat_shmem.c:838

References Assert(), PgStat_LocalState::dsa, dsa_detach(), dsa_release_in_place(), dshash_detach(), pgstat_release_all_entry_refs(), pgStatLocal, PgStat_ShmemControl::raw_dsa_area, PgStat_LocalState::shared_hash, and PgStat_LocalState::shmem.

Referenced by pgstat_shutdown_hook().

◆ pgstat_drop_all_entries()

void pgstat_drop_all_entries ( void  )

Definition at line 1090 of file pgstat_shmem.c.

1091{
1093}
void pgstat_drop_matching_entries(bool(*do_drop)(PgStatShared_HashEntry *, Datum), Datum match_data)

References pgstat_drop_matching_entries().

Referenced by pgstat_reset_after_failure().

◆ pgstat_drop_database_and_contents()

static void pgstat_drop_database_and_contents ( Oid  dboid)
static

Definition at line 943 of file pgstat_shmem.c.

944{
945 dshash_seq_status hstat;
947 uint64 not_freed_count = 0;
948
949 Assert(OidIsValid(dboid));
950
952
953 /*
954 * This backend might very well be the only backend holding a reference to
955 * about-to-be-dropped entries. Ensure that we're not preventing it from
956 * being cleaned up till later.
957 *
958 * Doing this separately from the dshash iteration below avoids having to
959 * do so while holding a partition lock on the shared hashtable.
960 */
962
963 /* some of the dshash entries are to be removed, take exclusive lock. */
965 while ((p = dshash_seq_next(&hstat)) != NULL)
966 {
967 if (p->dropped)
968 continue;
969
970 if (p->key.dboid != dboid)
971 continue;
972
973 if (!pgstat_drop_entry_internal(p, &hstat))
974 {
975 /*
976 * Even statistics for a dropped database might currently be
977 * accessed (consider e.g. database stats for pg_stat_database).
978 */
979 not_freed_count++;
980 }
981 }
982 dshash_seq_term(&hstat);
983
984 /*
985 * If some of the stats data could not be freed, signal the reference
986 * holders to run garbage collection of their cached pgStatLocal.shmem.
987 */
988 if (not_freed_count > 0)
990}
uint64_t uint64
Definition: c.h:540
#define OidIsValid(objectId)
Definition: c.h:775
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
void pgstat_request_entry_refs_gc(void)
Definition: pgstat_shmem.c:745
static void pgstat_release_db_entry_refs(Oid dboid)
Definition: pgstat_shmem.c:858
static bool pgstat_drop_entry_internal(PgStatShared_HashEntry *shent, dshash_seq_status *hstat)
Definition: pgstat_shmem.c:902

References Assert(), PgStat_HashKey::dboid, PgStatShared_HashEntry::dropped, dshash_seq_init(), dshash_seq_next(), dshash_seq_term(), PgStatShared_HashEntry::key, OidIsValid, pgstat_drop_entry_internal(), pgstat_release_db_entry_refs(), pgstat_request_entry_refs_gc(), pgStatLocal, and PgStat_LocalState::shared_hash.

Referenced by pgstat_drop_entry().

◆ pgstat_drop_entry()

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

Definition at line 1004 of file pgstat_shmem.c.

1005{
1006 PgStat_HashKey key = {0};
1008 bool freed = true;
1009
1010 key.kind = kind;
1011 key.dboid = dboid;
1012 key.objid = objid;
1013
1014 /* delete local reference */
1016 {
1017 PgStat_EntryRefHashEntry *lohashent =
1018 pgstat_entry_ref_hash_lookup(pgStatEntryRefHash, key);
1019
1020 if (lohashent)
1021 pgstat_release_entry_ref(lohashent->key, lohashent->entry_ref,
1022 true);
1023 }
1024
1025 /* mark entry in shared hashtable as deleted, drop if possible */
1026 shent = dshash_find(pgStatLocal.shared_hash, &key, true);
1027 if (shent)
1028 {
1029 freed = pgstat_drop_entry_internal(shent, NULL);
1030
1031 /*
1032 * Database stats contain other stats. Drop those as well when
1033 * dropping the database. XXX: Perhaps this should be done in a
1034 * slightly more principled way? But not obvious what that'd look
1035 * like, and so far this is the only case...
1036 */
1037 if (key.kind == PGSTAT_KIND_DATABASE)
1039 }
1040
1041 return freed;
1042}
void * dshash_find(dshash_table *hash_table, const void *key, bool exclusive)
Definition: dshash.c:390
#define PGSTAT_KIND_DATABASE
Definition: pgstat_kind.h:27
static void pgstat_release_entry_ref(PgStat_HashKey key, PgStat_EntryRef *entry_ref, bool discard_pending)
Definition: pgstat_shmem.c:612
static void pgstat_drop_database_and_contents(Oid dboid)
Definition: pgstat_shmem.c:943
static pgstat_entry_ref_hash_hash * pgStatEntryRefHash
Definition: pgstat_shmem.c:82
PgStat_EntryRef * entry_ref
Definition: pgstat_shmem.c:28

References dshash_find(), PgStat_EntryRefHashEntry::entry_ref, PgStat_EntryRefHashEntry::key, sort-test::key, pgstat_drop_database_and_contents(), pgstat_drop_entry_internal(), PGSTAT_KIND_DATABASE, pgstat_release_entry_ref(), pgStatEntryRefHash, pgStatLocal, and PgStat_LocalState::shared_hash.

Referenced by AtEOSubXact_PgStat_DroppedStats(), AtEOXact_PgStat_DroppedStats(), pgstat_drop_inj(), pgstat_drop_replslot(), pgstat_execute_transactional_drops(), pgstat_init_function_usage(), and pgstat_shutdown_hook().

◆ pgstat_drop_entry_internal()

static bool pgstat_drop_entry_internal ( PgStatShared_HashEntry shent,
dshash_seq_status hstat 
)
static

Definition at line 902 of file pgstat_shmem.c.

904{
905 Assert(shent->body != InvalidDsaPointer);
906
907 /* should already have released local reference */
909 Assert(!pgstat_entry_ref_hash_lookup(pgStatEntryRefHash, shent->key));
910
911 /*
912 * Signal that the entry is dropped - this will eventually cause other
913 * backends to release their references.
914 */
915 if (shent->dropped)
916 elog(ERROR,
917 "trying to drop stats entry already dropped: kind=%s dboid=%u objid=%" PRIu64 " refcount=%u generation=%u",
919 shent->key.dboid,
920 shent->key.objid,
923 shent->dropped = true;
924
925 /* release refcount marking entry as not dropped */
926 if (pg_atomic_sub_fetch_u32(&shent->refcount, 1) == 0)
927 {
928 pgstat_free_entry(shent, hstat);
929 return true;
930 }
931 else
932 {
933 if (!hstat)
935 return false;
936 }
937}
static uint32 pg_atomic_sub_fetch_u32(volatile pg_atomic_uint32 *ptr, int32 sub_)
Definition: atomics.h:437
#define InvalidDsaPointer
Definition: dsa.h:78
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:226
const PgStat_KindInfo * pgstat_get_kind_info(PgStat_Kind kind)
Definition: pgstat.c:1433
static void pgstat_free_entry(PgStatShared_HashEntry *shent, dshash_seq_status *hstat)
Definition: pgstat_shmem.c:872
const char *const name

References Assert(), PgStatShared_HashEntry::body, PgStat_HashKey::dboid, PgStatShared_HashEntry::dropped, dshash_release_lock(), elog, ERROR, PgStatShared_HashEntry::generation, InvalidDsaPointer, PgStatShared_HashEntry::key, PgStat_HashKey::kind, PgStat_KindInfo::name, PgStat_HashKey::objid, pg_atomic_read_u32(), pg_atomic_sub_fetch_u32(), pgstat_free_entry(), pgstat_get_kind_info(), pgStatEntryRefHash, pgStatLocal, PgStatShared_HashEntry::refcount, and PgStat_LocalState::shared_hash.

Referenced by pgstat_drop_database_and_contents(), pgstat_drop_entry(), and pgstat_drop_matching_entries().

◆ pgstat_drop_matching_entries()

void pgstat_drop_matching_entries ( bool(*)(PgStatShared_HashEntry *, Datum do_drop,
Datum  match_data 
)

Definition at line 1049 of file pgstat_shmem.c.

1051{
1052 dshash_seq_status hstat;
1054 uint64 not_freed_count = 0;
1055
1056 /* entries are removed, take an exclusive lock */
1058 while ((ps = dshash_seq_next(&hstat)) != NULL)
1059 {
1060 if (ps->dropped)
1061 continue;
1062
1063 if (do_drop != NULL && !do_drop(ps, match_data))
1064 continue;
1065
1066 /* delete local reference */
1068 {
1069 PgStat_EntryRefHashEntry *lohashent =
1070 pgstat_entry_ref_hash_lookup(pgStatEntryRefHash, ps->key);
1071
1072 if (lohashent)
1073 pgstat_release_entry_ref(lohashent->key, lohashent->entry_ref,
1074 true);
1075 }
1076
1077 if (!pgstat_drop_entry_internal(ps, &hstat))
1078 not_freed_count++;
1079 }
1080 dshash_seq_term(&hstat);
1081
1082 if (not_freed_count > 0)
1084}
struct parser_state ps

References dshash_seq_init(), dshash_seq_next(), dshash_seq_term(), PgStat_EntryRefHashEntry::entry_ref, PgStat_EntryRefHashEntry::key, pgstat_drop_entry_internal(), pgstat_release_entry_ref(), pgstat_request_entry_refs_gc(), pgStatEntryRefHash, pgStatLocal, ps, and PgStat_LocalState::shared_hash.

Referenced by injection_points_stats_drop(), and pgstat_drop_all_entries().

◆ pgstat_dsa_init_size()

static Size pgstat_dsa_init_size ( void  )
static

Definition at line 106 of file pgstat_shmem.c.

107{
108 Size sz;
109
110 /*
111 * The dshash header / initial buckets array needs to fit into "plain"
112 * shared memory, but it's beneficial to not need dsm segments
113 * immediately. A size of 256kB seems works well and is not
114 * disproportional compared to other constant sized shared memory
115 * allocations. NB: To avoid DSMs further, the user can configure
116 * min_dynamic_shared_memory.
117 */
118 sz = 256 * 1024;
119 Assert(dsa_minimum_size() <= sz);
120 return MAXALIGN(sz);
121}
#define MAXALIGN(LEN)
Definition: c.h:811
size_t Size
Definition: c.h:611
size_t dsa_minimum_size(void)
Definition: dsa.c:1211

References Assert(), dsa_minimum_size(), and MAXALIGN.

Referenced by StatsShmemInit(), and StatsShmemSize().

◆ pgstat_free_entry()

static void pgstat_free_entry ( PgStatShared_HashEntry shent,
dshash_seq_status hstat 
)
static

Definition at line 872 of file pgstat_shmem.c.

873{
874 dsa_pointer pdsa;
875 PgStat_Kind kind = shent->key.kind;
876
877 /*
878 * Fetch dsa pointer before deleting entry - that way we can free the
879 * memory after releasing the lock.
880 */
881 pdsa = shent->body;
882
883 if (!hstat)
885 else
887
888 dsa_free(pgStatLocal.dsa, pdsa);
889
890 /* Decrement entry count, if required. */
891 if (pgstat_get_kind_info(kind)->track_entry_count)
893}
static uint64 pg_atomic_sub_fetch_u64(volatile pg_atomic_uint64 *ptr, int64 sub_)
Definition: atomics.h:566
void dsa_free(dsa_area *area, dsa_pointer dp)
Definition: dsa.c:841
uint64 dsa_pointer
Definition: dsa.h:62
void dshash_delete_entry(dshash_table *hash_table, void *entry)
Definition: dshash.c:541
void dshash_delete_current(dshash_seq_status *status)
Definition: dshash.c:757
#define PgStat_Kind
Definition: pgstat_kind.h:17
pg_atomic_uint64 entry_counts[PGSTAT_KIND_MAX]

References PgStatShared_HashEntry::body, PgStat_LocalState::dsa, dsa_free(), dshash_delete_current(), dshash_delete_entry(), PgStat_ShmemControl::entry_counts, PgStatShared_HashEntry::key, PgStat_HashKey::kind, pg_atomic_sub_fetch_u64(), pgstat_get_kind_info(), PgStat_Kind, pgStatLocal, PgStat_LocalState::shared_hash, and PgStat_LocalState::shmem.

Referenced by pgstat_drop_entry_internal(), and pgstat_release_entry_ref().

◆ pgstat_gc_entry_refs()

static void pgstat_gc_entry_refs ( void  )
static

Definition at line 767 of file pgstat_shmem.c.

768{
769 pgstat_entry_ref_hash_iterator i;
771 uint64 curage;
772
774 Assert(curage != 0);
775
776 /*
777 * Some entries have been dropped or reinitialized. Invalidate cache
778 * pointer to them.
779 */
780 pgstat_entry_ref_hash_start_iterate(pgStatEntryRefHash, &i);
781 while ((ent = pgstat_entry_ref_hash_iterate(pgStatEntryRefHash, &i)) != NULL)
782 {
783 PgStat_EntryRef *entry_ref = ent->entry_ref;
784
785 Assert(!entry_ref->shared_stats ||
786 entry_ref->shared_stats->magic == 0xdeadbeef);
787
788 /*
789 * "generation" checks for the case of entries being reinitialized,
790 * and "dropped" for the case where these are.. dropped.
791 */
792 if (!entry_ref->shared_entry->dropped &&
794 entry_ref->generation)
795 continue;
796
797 /* cannot gc shared ref that has pending data */
798 if (entry_ref->pending != NULL)
799 continue;
800
801 pgstat_release_entry_ref(ent->key, entry_ref, false);
802 }
803
804 pgStatSharedRefAge = curage;
805}
static uint64 pg_atomic_read_u64(volatile pg_atomic_uint64 *ptr)
Definition: atomics.h:465
int i
Definition: isn.c:77
static int pgStatSharedRefAge
Definition: pgstat_shmem.c:83
pg_atomic_uint64 gc_request_count

References Assert(), PgStatShared_HashEntry::dropped, PgStat_EntryRefHashEntry::entry_ref, PgStat_ShmemControl::gc_request_count, PgStatShared_HashEntry::generation, PgStat_EntryRef::generation, i, PgStat_EntryRefHashEntry::key, PgStatShared_Common::magic, PgStat_EntryRef::pending, pg_atomic_read_u32(), pg_atomic_read_u64(), pgstat_release_entry_ref(), pgStatEntryRefHash, pgStatLocal, pgStatSharedRefAge, PgStat_EntryRef::shared_entry, PgStat_EntryRef::shared_stats, and PgStat_LocalState::shmem.

Referenced by pgstat_get_entry_ref().

◆ pgstat_get_entry_ref()

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

Definition at line 469 of file pgstat_shmem.c.

471{
472 PgStat_HashKey key = {0};
473 PgStatShared_HashEntry *shhashent;
474 PgStatShared_Common *shheader = NULL;
475 PgStat_EntryRef *entry_ref;
476
477 key.kind = kind;
478 key.dboid = dboid;
479 key.objid = objid;
480
481 /*
482 * passing in created_entry only makes sense if we possibly could create
483 * entry.
484 */
485 Assert(create || created_entry == NULL);
489
492
493 if (created_entry != NULL)
494 *created_entry = false;
495
496 /*
497 * Check if other backends dropped stats that could not be deleted because
498 * somebody held references to it. If so, check this backend's references.
499 * This is not expected to happen often. The location of the check is a
500 * bit random, but this is a relatively frequently called path, so better
501 * than most.
502 */
505
506 /*
507 * First check the lookup cache hashtable in local memory. If we find a
508 * match here we can avoid taking locks / causing contention.
509 */
510 if (pgstat_get_entry_ref_cached(key, &entry_ref))
511 return entry_ref;
512
513 Assert(entry_ref != NULL);
514
515 /*
516 * Do a lookup in the hash table first - it's quite likely that the entry
517 * already exists, and that way we only need a shared lock.
518 */
519 shhashent = dshash_find(pgStatLocal.shared_hash, &key, false);
520
521 if (create && !shhashent)
522 {
523 bool shfound;
524
525 /*
526 * It's possible that somebody created the entry since the above
527 * lookup. If so, fall through to the same path as if we'd have if it
528 * already had been created before the dshash_find() calls.
529 */
530 shhashent = dshash_find_or_insert(pgStatLocal.shared_hash, &key, &shfound);
531 if (!shfound)
532 {
533 shheader = pgstat_init_entry(kind, shhashent);
534 if (shheader == NULL)
535 {
536 /*
537 * Failed the allocation of a new entry, so clean up the
538 * shared hashtable before giving up.
539 */
541
543 (errcode(ERRCODE_OUT_OF_MEMORY),
544 errmsg("out of memory"),
545 errdetail("Failed while allocating entry %u/%u/%" PRIu64 ".",
546 key.kind, key.dboid, key.objid)));
547 }
548 pgstat_acquire_entry_ref(entry_ref, shhashent, shheader);
549
550 if (created_entry != NULL)
551 *created_entry = true;
552
553 return entry_ref;
554 }
555 }
556
557 if (!shhashent)
558 {
559 /*
560 * If we're not creating, delete the reference again. In all
561 * likelihood it's just a stats lookup - no point wasting memory for a
562 * shared ref to nothing...
563 */
564 pgstat_release_entry_ref(key, entry_ref, false);
565
566 return NULL;
567 }
568 else
569 {
570 /*
571 * Can get here either because dshash_find() found a match, or if
572 * dshash_find_or_insert() found a concurrently inserted entry.
573 */
574
575 if (shhashent->dropped && create)
576 {
577 /*
578 * There are legitimate cases where the old stats entry might not
579 * yet have been dropped by the time it's reused. The most obvious
580 * case are replication slot stats, where a new slot can be
581 * created with the same index just after dropping. But oid
582 * wraparound can lead to other cases as well. We just reset the
583 * stats to their plain state, while incrementing its "generation"
584 * in the shared entry for any remaining local references.
585 */
586 shheader = pgstat_reinit_entry(kind, shhashent);
587 pgstat_acquire_entry_ref(entry_ref, shhashent, shheader);
588
589 if (created_entry != NULL)
590 *created_entry = true;
591
592 return entry_ref;
593 }
594 else if (shhashent->dropped)
595 {
597 pgstat_release_entry_ref(key, entry_ref, false);
598
599 return NULL;
600 }
601 else
602 {
603 shheader = dsa_get_address(pgStatLocal.dsa, shhashent->body);
604 pgstat_acquire_entry_ref(entry_ref, shhashent, shheader);
605
606 return entry_ref;
607 }
608 }
609}
void * dsa_get_address(dsa_area *area, dsa_pointer dp)
Definition: dsa.c:957
void * dshash_find_or_insert(dshash_table *hash_table, const void *key, bool *found)
Definition: dshash.c:433
int errdetail(const char *fmt,...)
Definition: elog.c:1207
int errcode(int sqlerrcode)
Definition: elog.c:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#define ereport(elevel,...)
Definition: elog.h:150
#define pgstat_assert_is_up()
static void pgstat_setup_memcxt(void)
static void pgstat_setup_shared_refs(void)
Definition: pgstat_shmem.c:377
static PgStatShared_Common * pgstat_reinit_entry(PgStat_Kind kind, PgStatShared_HashEntry *shhashent)
Definition: pgstat_shmem.c:352
static void pgstat_acquire_entry_ref(PgStat_EntryRef *entry_ref, PgStatShared_HashEntry *shhashent, PgStatShared_Common *shheader)
Definition: pgstat_shmem.c:393
PgStatShared_Common * pgstat_init_entry(PgStat_Kind kind, PgStatShared_HashEntry *shhashent)
Definition: pgstat_shmem.c:308
static bool pgstat_get_entry_ref_cached(PgStat_HashKey key, PgStat_EntryRef **entry_ref_p)
Definition: pgstat_shmem.c:413
static void pgstat_gc_entry_refs(void)
Definition: pgstat_shmem.c:767
static bool pgstat_need_entry_refs_gc(void)
Definition: pgstat_shmem.c:751

References Assert(), PgStatShared_HashEntry::body, PgStatShared_HashEntry::dropped, PgStat_LocalState::dsa, dsa_get_address(), dshash_delete_entry(), dshash_find(), dshash_find_or_insert(), dshash_release_lock(), ereport, errcode(), errdetail(), errmsg(), ERROR, PgStat_ShmemControl::is_shutdown, sort-test::key, pgstat_acquire_entry_ref(), pgstat_assert_is_up, pgstat_gc_entry_refs(), pgstat_get_entry_ref_cached(), pgstat_init_entry(), pgstat_need_entry_refs_gc(), pgstat_reinit_entry(), pgstat_release_entry_ref(), pgstat_setup_memcxt(), pgstat_setup_shared_refs(), pgStatLocal, PgStat_LocalState::shared_hash, and PgStat_LocalState::shmem.

Referenced by pgstat_acquire_replslot(), pgstat_create_subscription(), pgstat_create_transactional(), pgstat_fetch_entry(), pgstat_fetch_pending_entry(), pgstat_get_entry_ref_locked(), pgstat_have_entry(), pgstat_prep_pending_entry(), pgstat_prepare_report_checksum_failure(), pgstat_report_checksum_failures_in_db(), and pgstat_reset_entry().

◆ pgstat_get_entry_ref_cached()

static bool pgstat_get_entry_ref_cached ( PgStat_HashKey  key,
PgStat_EntryRef **  entry_ref_p 
)
static

Definition at line 413 of file pgstat_shmem.c.

414{
415 bool found;
416 PgStat_EntryRefHashEntry *cache_entry;
417
418 /*
419 * We immediately insert a cache entry, because it avoids 1) multiple
420 * hashtable lookups in case of a cache miss 2) having to deal with
421 * out-of-memory errors after incrementing PgStatShared_Common->refcount.
422 */
423
424 cache_entry = pgstat_entry_ref_hash_insert(pgStatEntryRefHash, key, &found);
425
426 if (!found || !cache_entry->entry_ref)
427 {
428 PgStat_EntryRef *entry_ref;
429
430 cache_entry->entry_ref = entry_ref =
432 sizeof(PgStat_EntryRef));
433 entry_ref->shared_stats = NULL;
434 entry_ref->shared_entry = NULL;
435 entry_ref->pending = NULL;
436
437 found = false;
438 }
439 else if (cache_entry->entry_ref->shared_stats == NULL)
440 {
441 Assert(cache_entry->entry_ref->pending == NULL);
442 found = false;
443 }
444 else
445 {
447
448 entry_ref = cache_entry->entry_ref;
449 Assert(entry_ref->shared_entry != NULL);
450 Assert(entry_ref->shared_stats != NULL);
451
452 Assert(entry_ref->shared_stats->magic == 0xdeadbeef);
453 /* should have at least our reference */
455 }
456
457 *entry_ref_p = cache_entry->entry_ref;
458 return found;
459}
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:223
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1229
static MemoryContext pgStatSharedRefContext
Definition: pgstat_shmem.c:90

References Assert(), PgStat_EntryRefHashEntry::entry_ref, sort-test::key, MemoryContextAlloc(), PgStat_EntryRef::pending, pg_atomic_read_u32(), PG_USED_FOR_ASSERTS_ONLY, pgStatEntryRefHash, pgStatSharedRefContext, PgStat_EntryRef::shared_entry, and PgStat_EntryRef::shared_stats.

Referenced by pgstat_get_entry_ref().

◆ pgstat_get_entry_ref_locked()

PgStat_EntryRef * pgstat_get_entry_ref_locked ( PgStat_Kind  kind,
Oid  dboid,
uint64  objid,
bool  nowait 
)

Definition at line 729 of file pgstat_shmem.c.

731{
732 PgStat_EntryRef *entry_ref;
733
734 /* find shared table stats entry corresponding to the local entry */
735 entry_ref = pgstat_get_entry_ref(kind, dboid, objid, true, NULL);
736
737 /* lock the shared entry to protect the content, skip if failed */
738 if (!pgstat_lock_entry(entry_ref, nowait))
739 return NULL;
740
741 return entry_ref;
742}
PgStat_EntryRef * pgstat_get_entry_ref(PgStat_Kind kind, Oid dboid, uint64 objid, bool create, bool *created_entry)
Definition: pgstat_shmem.c:469
bool pgstat_lock_entry(PgStat_EntryRef *entry_ref, bool nowait)
Definition: pgstat_shmem.c:690

References pgstat_get_entry_ref(), and pgstat_lock_entry().

Referenced by pgstat_copy_relation_stats(), pgstat_create_backend(), pgstat_create_replslot(), pgstat_flush_backend(), pgstat_report_analyze(), pgstat_report_autovac(), pgstat_report_replslot(), pgstat_report_vacuum(), and pgstat_reset_database_timestamp().

◆ pgstat_init_entry()

PgStatShared_Common * pgstat_init_entry ( PgStat_Kind  kind,
PgStatShared_HashEntry shhashent 
)

Definition at line 308 of file pgstat_shmem.c.

310{
311 /* Create new stats entry. */
312 dsa_pointer chunk;
313 PgStatShared_Common *shheader;
314 const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind);
315
316 /*
317 * Initialize refcount to 1, marking it as valid / not dropped. The entry
318 * can't be freed before the initialization because it can't be found as
319 * long as we hold the dshash partition lock. Caller needs to increase
320 * further if a longer lived reference is needed.
321 */
322 pg_atomic_init_u32(&shhashent->refcount, 1);
323
324 /*
325 * Initialize "generation" to 0, as freshly created.
326 */
327 pg_atomic_init_u32(&shhashent->generation, 0);
328 shhashent->dropped = false;
329
331 kind_info->shared_size,
333 if (chunk == InvalidDsaPointer)
334 return NULL;
335
336 shheader = dsa_get_address(pgStatLocal.dsa, chunk);
337 shheader->magic = 0xdeadbeef;
338
339 /* Link the new entry from the hash entry. */
340 shhashent->body = chunk;
341
342 /* Increment entry count, if required. */
343 if (kind_info->track_entry_count)
345
346 LWLockInitialize(&shheader->lock, LWTRANCHE_PGSTATS_DATA);
347
348 return shheader;
349}
static void pg_atomic_init_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:219
static uint64 pg_atomic_fetch_add_u64(volatile pg_atomic_uint64 *ptr, int64 add_)
Definition: atomics.h:520
dsa_pointer dsa_allocate_extended(dsa_area *area, size_t size, int flags)
Definition: dsa.c:686
#define DSA_ALLOC_NO_OOM
Definition: dsa.h:74
#define DSA_ALLOC_ZERO
Definition: dsa.h:75
void LWLockInitialize(LWLock *lock, int tranche_id)
Definition: lwlock.c:698

References PgStatShared_HashEntry::body, PgStatShared_HashEntry::dropped, PgStat_LocalState::dsa, DSA_ALLOC_NO_OOM, DSA_ALLOC_ZERO, dsa_allocate_extended(), dsa_get_address(), PgStat_ShmemControl::entry_counts, PgStatShared_HashEntry::generation, InvalidDsaPointer, PgStatShared_Common::lock, LWLockInitialize(), PgStatShared_Common::magic, pg_atomic_fetch_add_u64(), pg_atomic_init_u32(), pgstat_get_kind_info(), pgStatLocal, PgStatShared_HashEntry::refcount, PgStat_KindInfo::shared_size, PgStat_LocalState::shmem, and PgStat_KindInfo::track_entry_count.

Referenced by pgstat_get_entry_ref(), and pgstat_read_statsfile().

◆ pgstat_lock_entry()

bool pgstat_lock_entry ( PgStat_EntryRef entry_ref,
bool  nowait 
)

Definition at line 690 of file pgstat_shmem.c.

691{
692 LWLock *lock = &entry_ref->shared_stats->lock;
693
694 if (nowait)
696
698 return true;
699}
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1174
bool LWLockConditionalAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1345
@ LW_EXCLUSIVE
Definition: lwlock.h:112
Definition: lwlock.h:42

References PgStatShared_Common::lock, LW_EXCLUSIVE, LWLockAcquire(), LWLockConditionalAcquire(), and PgStat_EntryRef::shared_stats.

Referenced by injection_stats_flush_cb(), pgstat_database_flush_cb(), pgstat_function_flush_cb(), pgstat_get_entry_ref_locked(), pgstat_relation_flush_cb(), pgstat_report_checksum_failures_in_db(), pgstat_reset_entry(), and pgstat_subscription_flush_cb().

◆ pgstat_lock_entry_shared()

bool pgstat_lock_entry_shared ( PgStat_EntryRef entry_ref,
bool  nowait 
)

Definition at line 708 of file pgstat_shmem.c.

709{
710 LWLock *lock = &entry_ref->shared_stats->lock;
711
712 if (nowait)
714
716 return true;
717}
@ LW_SHARED
Definition: lwlock.h:113

References PgStatShared_Common::lock, LW_SHARED, LWLockAcquire(), LWLockConditionalAcquire(), and PgStat_EntryRef::shared_stats.

Referenced by pgstat_fetch_entry().

◆ pgstat_need_entry_refs_gc()

static bool pgstat_need_entry_refs_gc ( void  )
static

Definition at line 751 of file pgstat_shmem.c.

752{
753 uint64 curage;
754
756 return false;
757
758 /* should have been initialized when creating pgStatEntryRefHash */
760
762
763 return pgStatSharedRefAge != curage;
764}

References Assert(), PgStat_ShmemControl::gc_request_count, pg_atomic_read_u64(), pgStatEntryRefHash, pgStatLocal, pgStatSharedRefAge, and PgStat_LocalState::shmem.

Referenced by pgstat_get_entry_ref().

◆ pgstat_reinit_entry()

static PgStatShared_Common * pgstat_reinit_entry ( PgStat_Kind  kind,
PgStatShared_HashEntry shhashent 
)
static

Definition at line 352 of file pgstat_shmem.c.

353{
354 PgStatShared_Common *shheader;
355
356 shheader = dsa_get_address(pgStatLocal.dsa, shhashent->body);
357
358 /* mark as not dropped anymore */
359 pg_atomic_fetch_add_u32(&shhashent->refcount, 1);
360
361 /*
362 * Increment "generation", to let any backend with local references know
363 * that what they point to is outdated.
364 */
365 pg_atomic_fetch_add_u32(&shhashent->generation, 1);
366 shhashent->dropped = false;
367
368 /* reinitialize content */
369 Assert(shheader->magic == 0xdeadbeef);
370 memset(pgstat_get_entry_data(kind, shheader), 0,
372
373 return shheader;
374}
static void * pgstat_get_entry_data(PgStat_Kind kind, PgStatShared_Common *entry)
static size_t pgstat_get_entry_len(PgStat_Kind kind)

References Assert(), PgStatShared_HashEntry::body, PgStatShared_HashEntry::dropped, PgStat_LocalState::dsa, dsa_get_address(), PgStatShared_HashEntry::generation, PgStatShared_Common::magic, pg_atomic_fetch_add_u32(), pgstat_get_entry_data(), pgstat_get_entry_len(), pgStatLocal, and PgStatShared_HashEntry::refcount.

Referenced by pgstat_get_entry_ref().

◆ pgstat_release_all_entry_refs()

static void pgstat_release_all_entry_refs ( bool  discard_pending)
static

Definition at line 838 of file pgstat_shmem.c.

839{
840 if (pgStatEntryRefHash == NULL)
841 return;
842
843 pgstat_release_matching_entry_refs(discard_pending, NULL, 0);
844 Assert(pgStatEntryRefHash->members == 0);
845 pgstat_entry_ref_hash_destroy(pgStatEntryRefHash);
846 pgStatEntryRefHash = NULL;
847}
static void pgstat_release_matching_entry_refs(bool discard_pending, ReleaseMatchCB match, Datum match_data)
Definition: pgstat_shmem.c:808

References Assert(), pgstat_release_matching_entry_refs(), and pgStatEntryRefHash.

Referenced by pgstat_detach_shmem().

◆ pgstat_release_db_entry_refs()

static void pgstat_release_db_entry_refs ( Oid  dboid)
static

Definition at line 858 of file pgstat_shmem.c.

859{
860 pgstat_release_matching_entry_refs( /* discard pending = */ true,
861 match_db,
862 ObjectIdGetDatum(dboid));
863}
static bool match_db(PgStat_EntryRefHashEntry *ent, Datum match_data)
Definition: pgstat_shmem.c:850
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:262

References match_db(), ObjectIdGetDatum(), and pgstat_release_matching_entry_refs().

Referenced by pgstat_drop_database_and_contents().

◆ pgstat_release_entry_ref()

static void pgstat_release_entry_ref ( PgStat_HashKey  key,
PgStat_EntryRef entry_ref,
bool  discard_pending 
)
static

Definition at line 612 of file pgstat_shmem.c.

614{
615 if (entry_ref && entry_ref->pending)
616 {
617 if (discard_pending)
619 else
620 elog(ERROR, "releasing ref with pending data");
621 }
622
623 if (entry_ref && entry_ref->shared_stats)
624 {
625 Assert(entry_ref->shared_stats->magic == 0xdeadbeef);
626 Assert(entry_ref->pending == NULL);
627
628 /*
629 * This can't race with another backend looking up the stats entry and
630 * increasing the refcount because it is not "legal" to create
631 * additional references to dropped entries.
632 */
633 if (pg_atomic_fetch_sub_u32(&entry_ref->shared_entry->refcount, 1) == 1)
634 {
636
637 /*
638 * We're the last referrer to this entry, try to drop the shared
639 * entry.
640 */
641
642 /* only dropped entries can reach a 0 refcount */
643 Assert(entry_ref->shared_entry->dropped);
644
646 &entry_ref->shared_entry->key,
647 true);
648 if (!shent)
649 elog(ERROR, "could not find just referenced shared stats entry");
650
651 /*
652 * This entry may have been reinitialized while trying to release
653 * it, so double-check that it has not been reused while holding a
654 * lock on its shared entry.
655 */
656 if (pg_atomic_read_u32(&entry_ref->shared_entry->generation) ==
657 entry_ref->generation)
658 {
659 /* Same "generation", so we're OK with the removal */
661 Assert(entry_ref->shared_entry == shent);
662 pgstat_free_entry(shent, NULL);
663 }
664 else
665 {
666 /*
667 * Shared stats entry has been reinitialized, so do not drop
668 * its shared entry, only release its lock.
669 */
671 }
672 }
673 }
674
675 if (!pgstat_entry_ref_hash_delete(pgStatEntryRefHash, key))
676 elog(ERROR, "entry ref vanished before deletion");
677
678 if (entry_ref)
679 pfree(entry_ref);
680}
static uint32 pg_atomic_fetch_sub_u32(volatile pg_atomic_uint32 *ptr, int32 sub_)
Definition: atomics.h:379
void pfree(void *pointer)
Definition: mcxt.c:1594
void pgstat_delete_pending_entry(PgStat_EntryRef *entry_ref)
Definition: pgstat.c:1314

References Assert(), PgStatShared_HashEntry::dropped, dshash_find(), dshash_release_lock(), elog, ERROR, PgStatShared_HashEntry::generation, PgStat_EntryRef::generation, PgStatShared_HashEntry::key, sort-test::key, PgStatShared_Common::magic, PgStat_EntryRef::pending, pfree(), pg_atomic_fetch_sub_u32(), pg_atomic_read_u32(), pgstat_delete_pending_entry(), pgstat_free_entry(), pgStatEntryRefHash, pgStatLocal, PgStatShared_HashEntry::refcount, PgStat_EntryRef::shared_entry, PgStat_LocalState::shared_hash, and PgStat_EntryRef::shared_stats.

Referenced by pgstat_drop_entry(), pgstat_drop_matching_entries(), pgstat_gc_entry_refs(), pgstat_get_entry_ref(), and pgstat_release_matching_entry_refs().

◆ pgstat_release_matching_entry_refs()

static void pgstat_release_matching_entry_refs ( bool  discard_pending,
ReleaseMatchCB  match,
Datum  match_data 
)
static

Definition at line 808 of file pgstat_shmem.c.

810{
811 pgstat_entry_ref_hash_iterator i;
813
814 if (pgStatEntryRefHash == NULL)
815 return;
816
817 pgstat_entry_ref_hash_start_iterate(pgStatEntryRefHash, &i);
818
819 while ((ent = pgstat_entry_ref_hash_iterate(pgStatEntryRefHash, &i))
820 != NULL)
821 {
822 Assert(ent->entry_ref != NULL);
823
824 if (match && !match(ent, match_data))
825 continue;
826
827 pgstat_release_entry_ref(ent->key, ent->entry_ref, discard_pending);
828 }
829}

References Assert(), PgStat_EntryRefHashEntry::entry_ref, i, PgStat_EntryRefHashEntry::key, pgstat_release_entry_ref(), and pgStatEntryRefHash.

Referenced by pgstat_release_all_entry_refs(), and pgstat_release_db_entry_refs().

◆ pgstat_request_entry_refs_gc()

◆ pgstat_reset_entries_of_kind()

void pgstat_reset_entries_of_kind ( PgStat_Kind  kind,
TimestampTz  ts 
)

Definition at line 1168 of file pgstat_shmem.c.

1169{
1171}
static bool match_kind(PgStatShared_HashEntry *p, Datum match_data)
void pgstat_reset_matching_entries(bool(*do_reset)(PgStatShared_HashEntry *, Datum), Datum match_data, TimestampTz ts)
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:222

References Int32GetDatum(), match_kind(), and pgstat_reset_matching_entries().

Referenced by pgstat_reset_of_kind().

◆ pgstat_reset_entry()

void pgstat_reset_entry ( PgStat_Kind  kind,
Oid  dboid,
uint64  objid,
TimestampTz  ts 
)

Definition at line 1112 of file pgstat_shmem.c.

1113{
1114 PgStat_EntryRef *entry_ref;
1115
1116 Assert(!pgstat_get_kind_info(kind)->fixed_amount);
1117
1118 entry_ref = pgstat_get_entry_ref(kind, dboid, objid, false, NULL);
1119 if (!entry_ref || entry_ref->shared_entry->dropped)
1120 return;
1121
1122 (void) pgstat_lock_entry(entry_ref, false);
1123 shared_stat_reset_contents(kind, entry_ref->shared_stats, ts);
1124 pgstat_unlock_entry(entry_ref);
1125}
static void shared_stat_reset_contents(PgStat_Kind kind, PgStatShared_Common *header, TimestampTz ts)
void pgstat_unlock_entry(PgStat_EntryRef *entry_ref)
Definition: pgstat_shmem.c:720

References Assert(), PgStatShared_HashEntry::dropped, pgstat_get_entry_ref(), pgstat_get_kind_info(), pgstat_lock_entry(), pgstat_unlock_entry(), PgStat_EntryRef::shared_entry, shared_stat_reset_contents(), and PgStat_EntryRef::shared_stats.

Referenced by pgstat_create_subscription(), and pgstat_reset().

◆ pgstat_reset_matching_entries()

void pgstat_reset_matching_entries ( bool(*)(PgStatShared_HashEntry *, Datum do_reset,
Datum  match_data,
TimestampTz  ts 
)

Definition at line 1132 of file pgstat_shmem.c.

1134{
1135 dshash_seq_status hstat;
1137
1138 /* dshash entry is not modified, take shared lock */
1139 dshash_seq_init(&hstat, pgStatLocal.shared_hash, false);
1140 while ((p = dshash_seq_next(&hstat)) != NULL)
1141 {
1142 PgStatShared_Common *header;
1143
1144 if (p->dropped)
1145 continue;
1146
1147 if (!do_reset(p, match_data))
1148 continue;
1149
1150 header = dsa_get_address(pgStatLocal.dsa, p->body);
1151
1152 LWLockAcquire(&header->lock, LW_EXCLUSIVE);
1153
1154 shared_stat_reset_contents(p->key.kind, header, ts);
1155
1156 LWLockRelease(&header->lock);
1157 }
1158 dshash_seq_term(&hstat);
1159}
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1894

References PgStatShared_HashEntry::body, PgStatShared_HashEntry::dropped, PgStat_LocalState::dsa, dsa_get_address(), dshash_seq_init(), dshash_seq_next(), dshash_seq_term(), PgStatShared_HashEntry::key, PgStat_HashKey::kind, PgStatShared_Common::lock, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), pgStatLocal, PgStat_LocalState::shared_hash, and shared_stat_reset_contents().

Referenced by pgstat_reset_counters(), and pgstat_reset_entries_of_kind().

◆ pgstat_setup_memcxt()

static void pgstat_setup_memcxt ( void  )
static

Definition at line 1174 of file pgstat_shmem.c.

1175{
1179 "PgStat Shared Ref",
1184 "PgStat Shared Ref Hash",
1186}
#define unlikely(x)
Definition: c.h:403
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:170
static MemoryContext pgStatEntryRefHashContext
Definition: pgstat_shmem.c:91

References ALLOCSET_SMALL_SIZES, AllocSetContextCreate, pgStatEntryRefHashContext, pgStatSharedRefContext, TopMemoryContext, and unlikely.

Referenced by pgstat_get_entry_ref().

◆ pgstat_setup_shared_refs()

static void pgstat_setup_shared_refs ( void  )
static

◆ pgstat_unlock_entry()

◆ shared_stat_reset_contents()

static void shared_stat_reset_contents ( PgStat_Kind  kind,
PgStatShared_Common header,
TimestampTz  ts 
)
static

Definition at line 1096 of file pgstat_shmem.c.

1098{
1099 const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind);
1100
1101 memset(pgstat_get_entry_data(kind, header), 0,
1102 pgstat_get_entry_len(kind));
1103
1104 if (kind_info->reset_timestamp_cb)
1105 kind_info->reset_timestamp_cb(header, ts);
1106}
void(* reset_timestamp_cb)(PgStatShared_Common *header, TimestampTz ts)

References pgstat_get_entry_data(), pgstat_get_entry_len(), pgstat_get_kind_info(), and PgStat_KindInfo::reset_timestamp_cb.

Referenced by pgstat_reset_entry(), and pgstat_reset_matching_entries().

◆ StatsShmemInit()

void StatsShmemInit ( void  )

Definition at line 156 of file pgstat_shmem.c.

157{
158 bool found;
159 Size sz;
160
161 sz = StatsShmemSize();
163 ShmemInitStruct("Shared Memory Stats", sz, &found);
164
166 {
167 dsa_area *dsa;
168 dshash_table *dsh;
170 char *p = (char *) ctl;
171
172 Assert(!found);
173
174 /* the allocation of pgStatLocal.shmem itself */
175 p += MAXALIGN(sizeof(PgStat_ShmemControl));
176
177 /*
178 * Create a small dsa allocation in plain shared memory. This is
179 * required because postmaster cannot use dsm segments. It also
180 * provides a small efficiency win.
181 */
182 ctl->raw_dsa_area = p;
183 dsa = dsa_create_in_place(ctl->raw_dsa_area,
185 LWTRANCHE_PGSTATS_DSA, NULL);
186 dsa_pin(dsa);
187
188 /*
189 * To ensure dshash is created in "plain" shared memory, temporarily
190 * limit size of dsa to the initial size of the dsa.
191 */
193
194 /*
195 * With the limit in place, create the dshash table. XXX: It'd be nice
196 * if there were dshash_create_in_place().
197 */
198 dsh = dshash_create(dsa, &dsh_params, NULL);
199 ctl->hash_handle = dshash_get_hash_table_handle(dsh);
200
201 /* lift limit set above */
202 dsa_set_size_limit(dsa, -1);
203
204 /*
205 * Postmaster will never access these again, thus free the local
206 * dsa/dshash references.
207 */
208 dshash_detach(dsh);
209 dsa_detach(dsa);
210
211 pg_atomic_init_u64(&ctl->gc_request_count, 1);
212
213 /* Do the per-kind initialization */
214 for (PgStat_Kind kind = PGSTAT_KIND_MIN; kind <= PGSTAT_KIND_MAX; kind++)
215 {
216 const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind);
217 char *ptr;
218
219 if (!kind_info)
220 continue;
221
222 /* initialize entry count tracking */
223 if (kind_info->track_entry_count)
224 pg_atomic_init_u64(&ctl->entry_counts[kind - 1], 0);
225
226 /* initialize fixed-numbered stats */
227 if (kind_info->fixed_amount)
228 {
229 if (pgstat_is_kind_builtin(kind))
230 ptr = ((char *) ctl) + kind_info->shared_ctl_off;
231 else
232 {
233 int idx = kind - PGSTAT_KIND_CUSTOM_MIN;
234
235 Assert(kind_info->shared_size != 0);
236 ctl->custom_data[idx] = ShmemAlloc(kind_info->shared_size);
237 ptr = ctl->custom_data[idx];
238 }
239
240 kind_info->init_shmem_cb(ptr);
241 }
242 }
243 }
244 else
245 {
246 Assert(found);
247 }
248}
Datum idx(PG_FUNCTION_ARGS)
Definition: _int_op.c:262
static void pg_atomic_init_u64(volatile pg_atomic_uint64 *ptr, uint64 val)
Definition: atomics.h:451
void dsa_set_size_limit(dsa_area *area, size_t limit)
Definition: dsa.c:1033
void dsa_pin(dsa_area *area)
Definition: dsa.c:990
#define dsa_create_in_place(place, size, tranche_id, segment)
Definition: dsa.h:122
dshash_table_handle dshash_get_hash_table_handle(dshash_table *hash_table)
Definition: dshash.c:367
dshash_table * dshash_create(dsa_area *area, const dshash_parameters *params, void *arg)
Definition: dshash.c:206
bool IsUnderPostmaster
Definition: globals.c:120
static bool pgstat_is_kind_builtin(PgStat_Kind kind)
Definition: pgstat_kind.h:61
#define PGSTAT_KIND_MAX
Definition: pgstat_kind.h:21
#define PGSTAT_KIND_CUSTOM_MIN
Definition: pgstat_kind.h:49
#define PGSTAT_KIND_MIN
Definition: pgstat_kind.h:20
static Size pgstat_dsa_init_size(void)
Definition: pgstat_shmem.c:106
Size StatsShmemSize(void)
Definition: pgstat_shmem.c:127
tree ctl
Definition: radixtree.h:1838
void * ShmemAlloc(Size size)
Definition: shmem.c:152
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:387
void(* init_shmem_cb)(void *stats)
Definition: dsa.c:348

References Assert(), ctl, dsa_create_in_place, dsa_detach(), dsa_pin(), dsa_set_size_limit(), dsh_params, dshash_create(), dshash_detach(), dshash_get_hash_table_handle(), PgStat_KindInfo::fixed_amount, idx(), PgStat_KindInfo::init_shmem_cb, IsUnderPostmaster, MAXALIGN, pg_atomic_init_u64(), pgstat_dsa_init_size(), pgstat_get_kind_info(), pgstat_is_kind_builtin(), PgStat_Kind, PGSTAT_KIND_CUSTOM_MIN, PGSTAT_KIND_MAX, PGSTAT_KIND_MIN, pgStatLocal, PgStat_KindInfo::shared_ctl_off, PgStat_KindInfo::shared_size, PgStat_LocalState::shmem, ShmemAlloc(), ShmemInitStruct(), StatsShmemSize(), and PgStat_KindInfo::track_entry_count.

Referenced by CreateOrAttachShmemStructs().

◆ StatsShmemSize()

Size StatsShmemSize ( void  )

Definition at line 127 of file pgstat_shmem.c.

128{
129 Size sz;
130
131 sz = MAXALIGN(sizeof(PgStat_ShmemControl));
132 sz = add_size(sz, pgstat_dsa_init_size());
133
134 /* Add shared memory for all the custom fixed-numbered statistics */
135 for (PgStat_Kind kind = PGSTAT_KIND_CUSTOM_MIN; kind <= PGSTAT_KIND_CUSTOM_MAX; kind++)
136 {
137 const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind);
138
139 if (!kind_info)
140 continue;
141 if (!kind_info->fixed_amount)
142 continue;
143
144 Assert(kind_info->shared_size != 0);
145
146 sz += MAXALIGN(kind_info->shared_size);
147 }
148
149 return sz;
150}
#define PGSTAT_KIND_CUSTOM_MAX
Definition: pgstat_kind.h:50
Size add_size(Size s1, Size s2)
Definition: shmem.c:493

References add_size(), Assert(), PgStat_KindInfo::fixed_amount, MAXALIGN, pgstat_dsa_init_size(), pgstat_get_kind_info(), PgStat_Kind, PGSTAT_KIND_CUSTOM_MAX, PGSTAT_KIND_CUSTOM_MIN, and PgStat_KindInfo::shared_size.

Referenced by CalculateShmemSize(), and StatsShmemInit().

Variable Documentation

◆ dsh_params

const dshash_parameters dsh_params
static
Initial value:
= {
sizeof(PgStat_HashKey),
LWTRANCHE_PGSTATS_HASH
}
void dshash_memcpy(void *dest, const void *src, size_t size, void *arg)
Definition: dshash.c:590
static uint32 pgstat_hash_hash_key(const void *d, size_t size, void *arg)
static int pgstat_cmp_hash_key(const void *a, const void *b, size_t size, void *arg)
struct PgStat_HashKey PgStat_HashKey

Definition at line 62 of file pgstat_shmem.c.

Referenced by pgstat_attach_shmem(), and StatsShmemInit().

◆ pgStatEntryRefHash

◆ pgStatEntryRefHashContext

MemoryContext pgStatEntryRefHashContext = NULL
static

Definition at line 91 of file pgstat_shmem.c.

Referenced by pgstat_setup_memcxt(), and pgstat_setup_shared_refs().

◆ pgStatSharedRefAge

int pgStatSharedRefAge = 0
static

◆ pgStatSharedRefContext

MemoryContext pgStatSharedRefContext = NULL
static

Definition at line 90 of file pgstat_shmem.c.

Referenced by pgstat_get_entry_ref_cached(), and pgstat_setup_memcxt().