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, Oid objoid, 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, Oid objoid, 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, Oid objoid)
 
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, Oid objoid, 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 727 of file pgstat_shmem.c.

728 {
729  Oid dboid = DatumGetObjectId(match_data);
730 
731  return ent->key.dboid == dboid;
732 }
static Oid DatumGetObjectId(Datum X)
Definition: postgres.h:242
unsigned int Oid
Definition: postgres_ext.h:31

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 984 of file pgstat_shmem.c.

985 {
986  return p->key.kind == DatumGetInt32(match_data);
987 }
static int32 DatumGetInt32(Datum X)
Definition: postgres.h:202
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 323 of file pgstat_shmem.c.

326 {
327  Assert(shheader->magic == 0xdeadbeef);
328  Assert(pg_atomic_read_u32(&shhashent->refcount) > 0);
329 
330  pg_atomic_fetch_add_u32(&shhashent->refcount, 1);
331 
333 
334  entry_ref->shared_stats = shheader;
335  entry_ref->shared_entry = shhashent;
336 }
static uint32 pg_atomic_fetch_add_u32(volatile pg_atomic_uint32 *ptr, int32 add_)
Definition: atomics.h:361
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition: atomics.h:234
void dshash_release_lock(dshash_table *hash_table, void *entry)
Definition: dshash.c:558
Assert(fmt[strlen(fmt) - 1] !='\n')
PgStat_LocalState pgStatLocal
Definition: pgstat.c:193
pg_atomic_uint32 refcount
PgStatShared_Common * shared_stats
PgStatShared_HashEntry * shared_entry
dshash_table * shared_hash

References Assert(), dshash_release_lock(), 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 218 of file pgstat_shmem.c.

219 {
220  MemoryContext oldcontext;
221 
222  Assert(pgStatLocal.dsa == NULL);
223 
224  /* stats shared memory persists for the backend lifetime */
226 
228  NULL);
230 
233 
234  MemoryContextSwitchTo(oldcontext);
235 }
void dsa_pin_mapping(dsa_area *area)
Definition: dsa.c:635
dsa_area * dsa_attach_in_place(void *place, dsm_segment *segment)
Definition: dsa.c:545
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:137
static const dshash_parameters dsh_params
Definition: pgstat_shmem.c:62
MemoryContextSwitchTo(old_ctx)
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 238 of file pgstat_shmem.c.

239 {
241 
242  /* we shouldn't leave references to shared stats */
244 
246  pgStatLocal.shared_hash = NULL;
247 
249  pgStatLocal.dsa = NULL;
250 }
void dsa_detach(dsa_area *area)
Definition: dsa.c:1952
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:715

References Assert(), PgStat_LocalState::dsa, dsa_detach(), dshash_detach(), pgstat_release_all_entry_refs(), pgStatLocal, and PgStat_LocalState::shared_hash.

Referenced by pgstat_shutdown_hook().

◆ pgstat_drop_all_entries()

void pgstat_drop_all_entries ( void  )

Definition at line 896 of file pgstat_shmem.c.

897 {
898  dshash_seq_status hstat;
900  uint64 not_freed_count = 0;
901 
902  dshash_seq_init(&hstat, pgStatLocal.shared_hash, true);
903  while ((ps = dshash_seq_next(&hstat)) != NULL)
904  {
905  if (ps->dropped)
906  continue;
907 
908  if (!pgstat_drop_entry_internal(ps, &hstat))
909  not_freed_count++;
910  }
911  dshash_seq_term(&hstat);
912 
913  if (not_freed_count > 0)
915 }
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
struct parser_state ps
void pgstat_request_entry_refs_gc(void)
Definition: pgstat_shmem.c:629
static bool pgstat_drop_entry_internal(PgStatShared_HashEntry *shent, dshash_seq_status *hstat)
Definition: pgstat_shmem.c:774

References dshash_seq_init(), dshash_seq_next(), dshash_seq_term(), pgstat_drop_entry_internal(), pgstat_request_entry_refs_gc(), pgStatLocal, ps, and PgStat_LocalState::shared_hash.

Referenced by pgstat_reset_after_failure().

◆ pgstat_drop_database_and_contents()

static void pgstat_drop_database_and_contents ( Oid  dboid)
static

Definition at line 809 of file pgstat_shmem.c.

810 {
811  dshash_seq_status hstat;
813  uint64 not_freed_count = 0;
814 
815  Assert(OidIsValid(dboid));
816 
817  Assert(pgStatLocal.shared_hash != NULL);
818 
819  /*
820  * This backend might very well be the only backend holding a reference to
821  * about-to-be-dropped entries. Ensure that we're not preventing it from
822  * being cleaned up till later.
823  *
824  * Doing this separately from the dshash iteration below avoids having to
825  * do so while holding a partition lock on the shared hashtable.
826  */
828 
829  /* some of the dshash entries are to be removed, take exclusive lock. */
830  dshash_seq_init(&hstat, pgStatLocal.shared_hash, true);
831  while ((p = dshash_seq_next(&hstat)) != NULL)
832  {
833  if (p->dropped)
834  continue;
835 
836  if (p->key.dboid != dboid)
837  continue;
838 
839  if (!pgstat_drop_entry_internal(p, &hstat))
840  {
841  /*
842  * Even statistics for a dropped database might currently be
843  * accessed (consider e.g. database stats for pg_stat_database).
844  */
845  not_freed_count++;
846  }
847  }
848  dshash_seq_term(&hstat);
849 
850  /*
851  * If some of the stats data could not be freed, signal the reference
852  * holders to run garbage collection of their cached pgStatShmLookupCache.
853  */
854  if (not_freed_count > 0)
856 }
#define OidIsValid(objectId)
Definition: c.h:762
static void pgstat_release_db_entry_refs(Oid dboid)
Definition: pgstat_shmem.c:735

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,
Oid  objoid 
)

Definition at line 859 of file pgstat_shmem.c.

860 {
861  PgStat_HashKey key = {.kind = kind,.dboid = dboid,.objoid = objoid};
862  PgStatShared_HashEntry *shent;
863  bool freed = true;
864 
865  /* delete local reference */
866  if (pgStatEntryRefHash)
867  {
868  PgStat_EntryRefHashEntry *lohashent =
869  pgstat_entry_ref_hash_lookup(pgStatEntryRefHash, key);
870 
871  if (lohashent)
872  pgstat_release_entry_ref(lohashent->key, lohashent->entry_ref,
873  true);
874  }
875 
876  /* mark entry in shared hashtable as deleted, drop if possible */
877  shent = dshash_find(pgStatLocal.shared_hash, &key, true);
878  if (shent)
879  {
880  freed = pgstat_drop_entry_internal(shent, NULL);
881 
882  /*
883  * Database stats contain other stats. Drop those as well when
884  * dropping the database. XXX: Perhaps this should be done in a
885  * slightly more principled way? But not obvious what that'd look
886  * like, and so far this is the only case...
887  */
888  if (key.kind == PGSTAT_KIND_DATABASE)
890  }
891 
892  return freed;
893 }
void * dshash_find(dshash_table *hash_table, const void *key, bool exclusive)
Definition: dshash.c:390
@ PGSTAT_KIND_DATABASE
Definition: pgstat.h:41
static void pgstat_release_entry_ref(PgStat_HashKey key, PgStat_EntryRef *entry_ref, bool discard_pending)
Definition: pgstat_shmem.c:522
static void pgstat_drop_database_and_contents(Oid dboid)
Definition: pgstat_shmem.c:809
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_replslot(), pgstat_execute_transactional_drops(), and pgstat_init_function_usage().

◆ pgstat_drop_entry_internal()

static bool pgstat_drop_entry_internal ( PgStatShared_HashEntry shent,
dshash_seq_status hstat 
)
static

Definition at line 774 of file pgstat_shmem.c.

776 {
777  Assert(shent->body != InvalidDsaPointer);
778 
779  /* should already have released local reference */
780  if (pgStatEntryRefHash)
781  Assert(!pgstat_entry_ref_hash_lookup(pgStatEntryRefHash, shent->key));
782 
783  /*
784  * Signal that the entry is dropped - this will eventually cause other
785  * backends to release their references.
786  */
787  if (shent->dropped)
788  elog(ERROR, "can only drop stats once");
789  shent->dropped = true;
790 
791  /* release refcount marking entry as not dropped */
792  if (pg_atomic_sub_fetch_u32(&shent->refcount, 1) == 0)
793  {
794  pgstat_free_entry(shent, hstat);
795  return true;
796  }
797  else
798  {
799  if (!hstat)
801  return false;
802  }
803 }
static uint32 pg_atomic_sub_fetch_u32(volatile pg_atomic_uint32 *ptr, int32 sub_)
Definition: atomics.h:434
#define InvalidDsaPointer
Definition: dsa.h:78
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:224
static void pgstat_free_entry(PgStatShared_HashEntry *shent, dshash_seq_status *hstat)
Definition: pgstat_shmem.c:749

References Assert(), PgStatShared_HashEntry::body, PgStatShared_HashEntry::dropped, dshash_release_lock(), elog, ERROR, InvalidDsaPointer, PgStatShared_HashEntry::key, pg_atomic_sub_fetch_u32(), pgstat_free_entry(), pgStatEntryRefHash, pgStatLocal, PgStatShared_HashEntry::refcount, and PgStat_LocalState::shared_hash.

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

◆ 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:798
size_t Size
Definition: c.h:592
size_t dsa_minimum_size(void)
Definition: dsa.c:1196

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 749 of file pgstat_shmem.c.

750 {
751  dsa_pointer pdsa;
752 
753  /*
754  * Fetch dsa pointer before deleting entry - that way we can free the
755  * memory after releasing the lock.
756  */
757  pdsa = shent->body;
758 
759  if (!hstat)
761  else
762  dshash_delete_current(hstat);
763 
764  dsa_free(pgStatLocal.dsa, pdsa);
765 }
void dsa_free(dsa_area *area, dsa_pointer dp)
Definition: dsa.c:826
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

References PgStatShared_HashEntry::body, PgStat_LocalState::dsa, dsa_free(), dshash_delete_current(), dshash_delete_entry(), pgStatLocal, and PgStat_LocalState::shared_hash.

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 651 of file pgstat_shmem.c.

652 {
653  pgstat_entry_ref_hash_iterator i;
655  uint64 curage;
656 
658  Assert(curage != 0);
659 
660  /*
661  * Some entries have been dropped. Invalidate cache pointer to them.
662  */
663  pgstat_entry_ref_hash_start_iterate(pgStatEntryRefHash, &i);
664  while ((ent = pgstat_entry_ref_hash_iterate(pgStatEntryRefHash, &i)) != NULL)
665  {
666  PgStat_EntryRef *entry_ref = ent->entry_ref;
667 
668  Assert(!entry_ref->shared_stats ||
669  entry_ref->shared_stats->magic == 0xdeadbeef);
670 
671  if (!entry_ref->shared_entry->dropped)
672  continue;
673 
674  /* cannot gc shared ref that has pending data */
675  if (entry_ref->pending != NULL)
676  continue;
677 
678  pgstat_release_entry_ref(ent->key, entry_ref, false);
679  }
680 
681  pgStatSharedRefAge = curage;
682 }
static uint64 pg_atomic_read_u64(volatile pg_atomic_uint64 *ptr)
Definition: atomics.h:462
int i
Definition: isn.c:73
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, i, PgStat_EntryRefHashEntry::key, PgStatShared_Common::magic, PgStat_EntryRef::pending, 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,
Oid  objoid,
bool  create,
bool created_entry 
)

Definition at line 398 of file pgstat_shmem.c.

400 {
401  PgStat_HashKey key = {.kind = kind,.dboid = dboid,.objoid = objoid};
402  PgStatShared_HashEntry *shhashent;
403  PgStatShared_Common *shheader = NULL;
404  PgStat_EntryRef *entry_ref;
405 
406  /*
407  * passing in created_entry only makes sense if we possibly could create
408  * entry.
409  */
410  Assert(create || created_entry == NULL);
412  Assert(pgStatLocal.shared_hash != NULL);
414 
417 
418  if (created_entry != NULL)
419  *created_entry = false;
420 
421  /*
422  * Check if other backends dropped stats that could not be deleted because
423  * somebody held references to it. If so, check this backend's references.
424  * This is not expected to happen often. The location of the check is a
425  * bit random, but this is a relatively frequently called path, so better
426  * than most.
427  */
430 
431  /*
432  * First check the lookup cache hashtable in local memory. If we find a
433  * match here we can avoid taking locks / causing contention.
434  */
435  if (pgstat_get_entry_ref_cached(key, &entry_ref))
436  return entry_ref;
437 
438  Assert(entry_ref != NULL);
439 
440  /*
441  * Do a lookup in the hash table first - it's quite likely that the entry
442  * already exists, and that way we only need a shared lock.
443  */
444  shhashent = dshash_find(pgStatLocal.shared_hash, &key, false);
445 
446  if (create && !shhashent)
447  {
448  bool shfound;
449 
450  /*
451  * It's possible that somebody created the entry since the above
452  * lookup. If so, fall through to the same path as if we'd have if it
453  * already had been created before the dshash_find() calls.
454  */
455  shhashent = dshash_find_or_insert(pgStatLocal.shared_hash, &key, &shfound);
456  if (!shfound)
457  {
458  shheader = pgstat_init_entry(kind, shhashent);
459  pgstat_acquire_entry_ref(entry_ref, shhashent, shheader);
460 
461  if (created_entry != NULL)
462  *created_entry = true;
463 
464  return entry_ref;
465  }
466  }
467 
468  if (!shhashent)
469  {
470  /*
471  * If we're not creating, delete the reference again. In all
472  * likelihood it's just a stats lookup - no point wasting memory for a
473  * shared ref to nothing...
474  */
475  pgstat_release_entry_ref(key, entry_ref, false);
476 
477  return NULL;
478  }
479  else
480  {
481  /*
482  * Can get here either because dshash_find() found a match, or if
483  * dshash_find_or_insert() found a concurrently inserted entry.
484  */
485 
486  if (shhashent->dropped && create)
487  {
488  /*
489  * There are legitimate cases where the old stats entry might not
490  * yet have been dropped by the time it's reused. The most obvious
491  * case are replication slot stats, where a new slot can be
492  * created with the same index just after dropping. But oid
493  * wraparound can lead to other cases as well. We just reset the
494  * stats to their plain state.
495  */
496  shheader = pgstat_reinit_entry(kind, shhashent);
497  pgstat_acquire_entry_ref(entry_ref, shhashent, shheader);
498 
499  if (created_entry != NULL)
500  *created_entry = true;
501 
502  return entry_ref;
503  }
504  else if (shhashent->dropped)
505  {
507  pgstat_release_entry_ref(key, entry_ref, false);
508 
509  return NULL;
510  }
511  else
512  {
513  shheader = dsa_get_address(pgStatLocal.dsa, shhashent->body);
514  pgstat_acquire_entry_ref(entry_ref, shhashent, shheader);
515 
516  return entry_ref;
517  }
518  }
519 }
void * dsa_get_address(dsa_area *area, dsa_pointer dp)
Definition: dsa.c:942
void * dshash_find_or_insert(dshash_table *hash_table, const void *key, bool *found)
Definition: dshash.c:433
#define pgstat_assert_is_up()
static void pgstat_setup_memcxt(void)
Definition: pgstat_shmem.c:996
PgStatShared_Common * pgstat_init_entry(PgStat_Kind kind, PgStatShared_HashEntry *shhashent)
Definition: pgstat_shmem.c:259
static void pgstat_setup_shared_refs(void)
Definition: pgstat_shmem.c:307
static PgStatShared_Common * pgstat_reinit_entry(PgStat_Kind kind, PgStatShared_HashEntry *shhashent)
Definition: pgstat_shmem.c:288
static void pgstat_acquire_entry_ref(PgStat_EntryRef *entry_ref, PgStatShared_HashEntry *shhashent, PgStatShared_Common *shheader)
Definition: pgstat_shmem.c:323
static bool pgstat_get_entry_ref_cached(PgStat_HashKey key, PgStat_EntryRef **entry_ref_p)
Definition: pgstat_shmem.c:342
static void pgstat_gc_entry_refs(void)
Definition: pgstat_shmem.c:651
static bool pgstat_need_entry_refs_gc(void)
Definition: pgstat_shmem.c:635

References Assert(), PgStatShared_HashEntry::body, PgStatShared_HashEntry::dropped, PgStat_LocalState::dsa, dsa_get_address(), dshash_find(), dshash_find_or_insert(), dshash_release_lock(), 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(), 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 342 of file pgstat_shmem.c.

343 {
344  bool found;
345  PgStat_EntryRefHashEntry *cache_entry;
346 
347  /*
348  * We immediately insert a cache entry, because it avoids 1) multiple
349  * hashtable lookups in case of a cache miss 2) having to deal with
350  * out-of-memory errors after incrementing PgStatShared_Common->refcount.
351  */
352 
353  cache_entry = pgstat_entry_ref_hash_insert(pgStatEntryRefHash, key, &found);
354 
355  if (!found || !cache_entry->entry_ref)
356  {
357  PgStat_EntryRef *entry_ref;
358 
359  cache_entry->entry_ref = entry_ref =
361  sizeof(PgStat_EntryRef));
362  entry_ref->shared_stats = NULL;
363  entry_ref->shared_entry = NULL;
364  entry_ref->pending = NULL;
365 
366  found = false;
367  }
368  else if (cache_entry->entry_ref->shared_stats == NULL)
369  {
370  Assert(cache_entry->entry_ref->pending == NULL);
371  found = false;
372  }
373  else
374  {
376 
377  entry_ref = cache_entry->entry_ref;
378  Assert(entry_ref->shared_entry != NULL);
379  Assert(entry_ref->shared_stats != NULL);
380 
381  Assert(entry_ref->shared_stats->magic == 0xdeadbeef);
382  /* should have at least our reference */
383  Assert(pg_atomic_read_u32(&entry_ref->shared_entry->refcount) > 0);
384  }
385 
386  *entry_ref_p = cache_entry->entry_ref;
387  return found;
388 }
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:169
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1168
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,
Oid  objoid,
bool  nowait 
)

Definition at line 613 of file pgstat_shmem.c.

615 {
616  PgStat_EntryRef *entry_ref;
617 
618  /* find shared table stats entry corresponding to the local entry */
619  entry_ref = pgstat_get_entry_ref(kind, dboid, objoid, true, NULL);
620 
621  /* lock the shared entry to protect the content, skip if failed */
622  if (!pgstat_lock_entry(entry_ref, nowait))
623  return NULL;
624 
625  return entry_ref;
626 }
PgStat_EntryRef * pgstat_get_entry_ref(PgStat_Kind kind, Oid dboid, Oid objoid, bool create, bool *created_entry)
Definition: pgstat_shmem.c:398
bool pgstat_lock_entry(PgStat_EntryRef *entry_ref, bool nowait)
Definition: pgstat_shmem.c:576

References pgstat_get_entry_ref(), and pgstat_lock_entry().

Referenced by pgstat_copy_relation_stats(), pgstat_create_replslot(), pgstat_report_analyze(), pgstat_report_autovac(), pgstat_report_checksum_failures_in_db(), 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 259 of file pgstat_shmem.c.

261 {
262  /* Create new stats entry. */
263  dsa_pointer chunk;
264  PgStatShared_Common *shheader;
265 
266  /*
267  * Initialize refcount to 1, marking it as valid / not dropped. The entry
268  * can't be freed before the initialization because it can't be found as
269  * long as we hold the dshash partition lock. Caller needs to increase
270  * further if a longer lived reference is needed.
271  */
272  pg_atomic_init_u32(&shhashent->refcount, 1);
273  shhashent->dropped = false;
274 
275  chunk = dsa_allocate0(pgStatLocal.dsa, pgstat_get_kind_info(kind)->shared_size);
276  shheader = dsa_get_address(pgStatLocal.dsa, chunk);
277  shheader->magic = 0xdeadbeef;
278 
279  /* Link the new entry from the hash entry. */
280  shhashent->body = chunk;
281 
283 
284  return shheader;
285 }
static void pg_atomic_init_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:216
#define dsa_allocate0(area, size)
Definition: dsa.h:113
void LWLockInitialize(LWLock *lock, int tranche_id)
Definition: lwlock.c:708
@ LWTRANCHE_PGSTATS_DATA
Definition: lwlock.h:205
const PgStat_KindInfo * pgstat_get_kind_info(PgStat_Kind kind)
Definition: pgstat.c:1263

References PgStatShared_HashEntry::body, PgStatShared_HashEntry::dropped, PgStat_LocalState::dsa, dsa_allocate0, dsa_get_address(), PgStatShared_Common::lock, LWLockInitialize(), LWTRANCHE_PGSTATS_DATA, PgStatShared_Common::magic, pg_atomic_init_u32(), pgstat_get_kind_info(), pgStatLocal, and PgStatShared_HashEntry::refcount.

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 576 of file pgstat_shmem.c.

577 {
578  LWLock *lock = &entry_ref->shared_stats->lock;
579 
580  if (nowait)
582 
584  return true;
585 }
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1169
bool LWLockConditionalAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1340
@ LW_EXCLUSIVE
Definition: lwlock.h:114
Definition: lwlock.h:42

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

Referenced by pgstat_database_flush_cb(), pgstat_function_flush_cb(), pgstat_get_entry_ref_locked(), pgstat_relation_flush_cb(), 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 592 of file pgstat_shmem.c.

593 {
594  LWLock *lock = &entry_ref->shared_stats->lock;
595 
596  if (nowait)
597  return LWLockConditionalAcquire(lock, LW_SHARED);
598 
599  LWLockAcquire(lock, LW_SHARED);
600  return true;
601 }
@ LW_SHARED
Definition: lwlock.h:115

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 635 of file pgstat_shmem.c.

636 {
637  uint64 curage;
638 
639  if (!pgStatEntryRefHash)
640  return false;
641 
642  /* should have been initialized when creating pgStatEntryRefHash */
644 
646 
647  return pgStatSharedRefAge != curage;
648 }

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 288 of file pgstat_shmem.c.

289 {
290  PgStatShared_Common *shheader;
291 
292  shheader = dsa_get_address(pgStatLocal.dsa, shhashent->body);
293 
294  /* mark as not dropped anymore */
295  pg_atomic_fetch_add_u32(&shhashent->refcount, 1);
296  shhashent->dropped = false;
297 
298  /* reinitialize content */
299  Assert(shheader->magic == 0xdeadbeef);
300  memset(pgstat_get_entry_data(kind, shheader), 0,
301  pgstat_get_entry_len(kind));
302 
303  return shheader;
304 }
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_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 715 of file pgstat_shmem.c.

716 {
717  if (pgStatEntryRefHash == NULL)
718  return;
719 
720  pgstat_release_matching_entry_refs(discard_pending, NULL, 0);
721  Assert(pgStatEntryRefHash->members == 0);
722  pgstat_entry_ref_hash_destroy(pgStatEntryRefHash);
723  pgStatEntryRefHash = NULL;
724 }
static void pgstat_release_matching_entry_refs(bool discard_pending, ReleaseMatchCB match, Datum match_data)
Definition: pgstat_shmem.c:685

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 735 of file pgstat_shmem.c.

736 {
737  pgstat_release_matching_entry_refs( /* discard pending = */ true,
738  match_db,
739  ObjectIdGetDatum(dboid));
740 }
static bool match_db(PgStat_EntryRefHashEntry *ent, Datum match_data)
Definition: pgstat_shmem.c:727
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252

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 522 of file pgstat_shmem.c.

524 {
525  if (entry_ref && entry_ref->pending)
526  {
527  if (discard_pending)
528  pgstat_delete_pending_entry(entry_ref);
529  else
530  elog(ERROR, "releasing ref with pending data");
531  }
532 
533  if (entry_ref && entry_ref->shared_stats)
534  {
535  Assert(entry_ref->shared_stats->magic == 0xdeadbeef);
536  Assert(entry_ref->pending == NULL);
537 
538  /*
539  * This can't race with another backend looking up the stats entry and
540  * increasing the refcount because it is not "legal" to create
541  * additional references to dropped entries.
542  */
543  if (pg_atomic_fetch_sub_u32(&entry_ref->shared_entry->refcount, 1) == 1)
544  {
545  PgStatShared_HashEntry *shent;
546 
547  /*
548  * We're the last referrer to this entry, try to drop the shared
549  * entry.
550  */
551 
552  /* only dropped entries can reach a 0 refcount */
553  Assert(entry_ref->shared_entry->dropped);
554 
556  &entry_ref->shared_entry->key,
557  true);
558  if (!shent)
559  elog(ERROR, "could not find just referenced shared stats entry");
560 
561  Assert(pg_atomic_read_u32(&entry_ref->shared_entry->refcount) == 0);
562  Assert(entry_ref->shared_entry == shent);
563 
564  pgstat_free_entry(shent, NULL);
565  }
566  }
567 
568  if (!pgstat_entry_ref_hash_delete(pgStatEntryRefHash, key))
569  elog(ERROR, "entry ref vanished before deletion");
570 
571  if (entry_ref)
572  pfree(entry_ref);
573 }
static uint32 pg_atomic_fetch_sub_u32(volatile pg_atomic_uint32 *ptr, int32 sub_)
Definition: atomics.h:376
void pfree(void *pointer)
Definition: mcxt.c:1508
void pgstat_delete_pending_entry(PgStat_EntryRef *entry_ref)
Definition: pgstat.c:1156

References Assert(), PgStatShared_HashEntry::dropped, dshash_find(), elog, ERROR, 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_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 685 of file pgstat_shmem.c.

687 {
688  pgstat_entry_ref_hash_iterator i;
690 
691  if (pgStatEntryRefHash == NULL)
692  return;
693 
694  pgstat_entry_ref_hash_start_iterate(pgStatEntryRefHash, &i);
695 
696  while ((ent = pgstat_entry_ref_hash_iterate(pgStatEntryRefHash, &i))
697  != NULL)
698  {
699  Assert(ent->entry_ref != NULL);
700 
701  if (match && !match(ent, match_data))
702  continue;
703 
704  pgstat_release_entry_ref(ent->key, ent->entry_ref, discard_pending);
705  }
706 }

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()

void pgstat_request_entry_refs_gc ( void  )

◆ pgstat_reset_entries_of_kind()

void pgstat_reset_entries_of_kind ( PgStat_Kind  kind,
TimestampTz  ts 
)

Definition at line 990 of file pgstat_shmem.c.

991 {
993 }
static bool match_kind(PgStatShared_HashEntry *p, Datum match_data)
Definition: pgstat_shmem.c:984
void pgstat_reset_matching_entries(bool(*do_reset)(PgStatShared_HashEntry *, Datum), Datum match_data, TimestampTz ts)
Definition: pgstat_shmem.c:954
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:212

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,
Oid  objoid,
TimestampTz  ts 
)

Definition at line 934 of file pgstat_shmem.c.

935 {
936  PgStat_EntryRef *entry_ref;
937 
938  Assert(!pgstat_get_kind_info(kind)->fixed_amount);
939 
940  entry_ref = pgstat_get_entry_ref(kind, dboid, objoid, false, NULL);
941  if (!entry_ref || entry_ref->shared_entry->dropped)
942  return;
943 
944  (void) pgstat_lock_entry(entry_ref, false);
945  shared_stat_reset_contents(kind, entry_ref->shared_stats, ts);
946  pgstat_unlock_entry(entry_ref);
947 }
static void shared_stat_reset_contents(PgStat_Kind kind, PgStatShared_Common *header, TimestampTz ts)
Definition: pgstat_shmem.c:918
void pgstat_unlock_entry(PgStat_EntryRef *entry_ref)
Definition: pgstat_shmem.c:604

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 954 of file pgstat_shmem.c.

956 {
957  dshash_seq_status hstat;
959 
960  /* dshash entry is not modified, take shared lock */
961  dshash_seq_init(&hstat, pgStatLocal.shared_hash, false);
962  while ((p = dshash_seq_next(&hstat)) != NULL)
963  {
964  PgStatShared_Common *header;
965 
966  if (p->dropped)
967  continue;
968 
969  if (!do_reset(p, match_data))
970  continue;
971 
972  header = dsa_get_address(pgStatLocal.dsa, p->body);
973 
974  LWLockAcquire(&header->lock, LW_EXCLUSIVE);
975 
976  shared_stat_reset_contents(p->key.kind, header, ts);
977 
978  LWLockRelease(&header->lock);
979  }
980  dshash_seq_term(&hstat);
981 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1782

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 996 of file pgstat_shmem.c.

997 {
1001  "PgStat Shared Ref",
1006  "PgStat Shared Ref Hash",
1008 }
#define unlikely(x)
Definition: c.h:298
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:163
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 918 of file pgstat_shmem.c.

920 {
921  const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind);
922 
923  memset(pgstat_get_entry_data(kind, header), 0,
924  pgstat_get_entry_len(kind));
925 
926  if (kind_info->reset_timestamp_cb)
927  kind_info->reset_timestamp_cb(header, ts);
928 }
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 141 of file pgstat_shmem.c.

142 {
143  bool found;
144  Size sz;
145 
146  sz = StatsShmemSize();
148  ShmemInitStruct("Shared Memory Stats", sz, &found);
149 
150  if (!IsUnderPostmaster)
151  {
152  dsa_area *dsa;
153  dshash_table *dsh;
155  char *p = (char *) ctl;
156 
157  Assert(!found);
158 
159  /* the allocation of pgStatLocal.shmem itself */
160  p += MAXALIGN(sizeof(PgStat_ShmemControl));
161 
162  /*
163  * Create a small dsa allocation in plain shared memory. This is
164  * required because postmaster cannot use dsm segments. It also
165  * provides a small efficiency win.
166  */
167  ctl->raw_dsa_area = p;
169  dsa = dsa_create_in_place(ctl->raw_dsa_area,
172  dsa_pin(dsa);
173 
174  /*
175  * To ensure dshash is created in "plain" shared memory, temporarily
176  * limit size of dsa to the initial size of the dsa.
177  */
179 
180  /*
181  * With the limit in place, create the dshash table. XXX: It'd be nice
182  * if there were dshash_create_in_place().
183  */
184  dsh = dshash_create(dsa, &dsh_params, NULL);
185  ctl->hash_handle = dshash_get_hash_table_handle(dsh);
186 
187  /* lift limit set above */
188  dsa_set_size_limit(dsa, -1);
189 
190  /*
191  * Postmaster will never access these again, thus free the local
192  * dsa/dshash references.
193  */
194  dshash_detach(dsh);
195  dsa_detach(dsa);
196 
197  pg_atomic_init_u64(&ctl->gc_request_count, 1);
198 
199 
200  /* initialize fixed-numbered stats */
201  LWLockInitialize(&ctl->archiver.lock, LWTRANCHE_PGSTATS_DATA);
202  LWLockInitialize(&ctl->bgwriter.lock, LWTRANCHE_PGSTATS_DATA);
203  LWLockInitialize(&ctl->checkpointer.lock, LWTRANCHE_PGSTATS_DATA);
206 
207  for (int i = 0; i < BACKEND_NUM_TYPES; i++)
208  LWLockInitialize(&ctl->io.locks[i],
210  }
211  else
212  {
213  Assert(found);
214  }
215 }
static void pg_atomic_init_u64(volatile pg_atomic_uint64 *ptr, uint64 val)
Definition: atomics.h:448
void dsa_set_size_limit(dsa_area *area, size_t limit)
Definition: dsa.c:1018
void dsa_pin(dsa_area *area)
Definition: dsa.c:975
#define dsa_create_in_place(place, size, tranch_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:117
@ LWTRANCHE_PGSTATS_DSA
Definition: lwlock.h:203
#define BACKEND_NUM_TYPES
Definition: miscadmin.h:370
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:1807
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:387
Definition: dsa.c:348

References Assert(), BACKEND_NUM_TYPES, ctl, dsa_create_in_place, dsa_detach(), dsa_pin(), dsa_set_size_limit(), dsh_params, dshash_create(), dshash_detach(), dshash_get_hash_table_handle(), i, IsUnderPostmaster, LWLockInitialize(), LWTRANCHE_PGSTATS_DATA, LWTRANCHE_PGSTATS_DSA, MAXALIGN, pg_atomic_init_u64(), pgstat_dsa_init_size(), pgStatLocal, PgStat_LocalState::shmem, ShmemInitStruct(), and StatsShmemSize().

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  return sz;
135 }
Size add_size(Size s1, Size s2)
Definition: shmem.c:493

References add_size(), MAXALIGN, and pgstat_dsa_init_size().

Referenced by CalculateShmemSize(), and StatsShmemInit().

Variable Documentation

◆ dsh_params

const dshash_parameters dsh_params
static
Initial value:
= {
sizeof(PgStat_HashKey),
}
void dshash_memcpy(void *dest, const void *src, size_t size, void *arg)
Definition: dshash.c:590
@ LWTRANCHE_PGSTATS_HASH
Definition: lwlock.h:204
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().