#ifndef PGSTAT_INTERNAL_H
#define PGSTAT_INTERNAL_H
#include "common/hashfn_unstable.h"
#include "lib/dshash.h"
#include "lib/ilist.h"
#include "pgstat.h"
#include "storage/lwlock.h"
#include "utils/dsa.h"
typedef struct PgStat_HashKey
{
PgStat_Kind kind;
Oid dboid;
Oid objoid;
} PgStat_HashKey;
typedef struct PgStatShared_HashEntry
{
PgStat_HashKey key;
bool dropped;
pg_atomic_uint32 refcount;
pg_atomic_uint32 generation;
dsa_pointer body;
} PgStatShared_HashEntry;
typedef struct PgStatShared_Common
{
uint32 magic;
LWLock lock;
} PgStatShared_Common;
typedef struct PgStat_EntryRef
{
PgStatShared_HashEntry *shared_entry;
PgStatShared_Common *shared_stats;
uint32 generation;
void *pending;
dlist_node pending_node;
} PgStat_EntryRef;
typedef struct PgStat_SubXactStatus
{
int nest_level;
struct PgStat_SubXactStatus *prev;
dclist_head pending_drops;
PgStat_TableXactStatus *first;
} PgStat_SubXactStatus;
typedef struct PgStat_KindInfo
{
bool fixed_amount:1;
bool accessed_across_databases:1;
bool named_on_disk:1;
uint32 shared_size;
uint32 shared_data_off;
uint32 shared_data_len;
uint32 pending_size;
bool (*flush_pending_cb) (PgStat_EntryRef *sr, bool nowait);
void (*delete_pending_cb) (PgStat_EntryRef *sr);
void (*reset_timestamp_cb) (PgStatShared_Common *header, TimestampTz ts);
void (*to_serialized_name) (const PgStat_HashKey *key,
const PgStatShared_Common *header, NameData *name);
bool (*from_serialized_name) (const NameData *name, PgStat_HashKey *key);
void (*reset_all_cb) (TimestampTz ts);
void (*snapshot_cb) (void);
const char *const name;
} PgStat_KindInfo;
static const char *const slru_names[] = {
"commit_timestamp",
"multixact_member",
"multixact_offset",
"notify",
"serializable",
"subtransaction",
"transaction",
"other"
};
#define SLRU_NUM_ELEMENTS lengthof(slru_names)
typedef struct PgStatShared_Archiver
{
LWLock lock;
uint32 changecount;
PgStat_ArchiverStats stats;
PgStat_ArchiverStats reset_offset;
} PgStatShared_Archiver;
typedef struct PgStatShared_BgWriter
{
LWLock lock;
uint32 changecount;
PgStat_BgWriterStats stats;
PgStat_BgWriterStats reset_offset;
} PgStatShared_BgWriter;
typedef struct PgStatShared_Checkpointer
{
LWLock lock;
uint32 changecount;
PgStat_CheckpointerStats stats;
PgStat_CheckpointerStats reset_offset;
} PgStatShared_Checkpointer;
typedef struct PgStatShared_IO
{
LWLock locks[BACKEND_NUM_TYPES];
PgStat_IO stats;
} PgStatShared_IO;
typedef struct PgStatShared_SLRU
{
LWLock lock;
PgStat_SLRUStats stats[SLRU_NUM_ELEMENTS];
} PgStatShared_SLRU;
typedef struct PgStatShared_Wal
{
LWLock lock;
PgStat_WalStats stats;
} PgStatShared_Wal;
typedef struct PgStatShared_Database
{
PgStatShared_Common header;
PgStat_StatDBEntry stats;
} PgStatShared_Database;
typedef struct PgStatShared_Relation
{
PgStatShared_Common header;
PgStat_StatTabEntry stats;
} PgStatShared_Relation;
typedef struct PgStatShared_Function
{
PgStatShared_Common header;
PgStat_StatFuncEntry stats;
} PgStatShared_Function;
typedef struct PgStatShared_Subscription
{
PgStatShared_Common header;
PgStat_StatSubEntry stats;
} PgStatShared_Subscription;
typedef struct PgStatShared_ReplSlot
{
PgStatShared_Common header;
PgStat_StatReplSlotEntry stats;
} PgStatShared_ReplSlot;
typedef struct PgStat_ShmemControl
{
void *raw_dsa_area;
dshash_table_handle hash_handle;
bool is_shutdown;
pg_atomic_uint64 gc_request_count;
PgStatShared_Archiver archiver;
PgStatShared_BgWriter bgwriter;
PgStatShared_Checkpointer checkpointer;
PgStatShared_IO io;
PgStatShared_SLRU slru;
PgStatShared_Wal wal;
} PgStat_ShmemControl;
typedef struct PgStat_Snapshot
{
PgStat_FetchConsistency mode;
TimestampTz snapshot_timestamp;
bool fixed_valid[PGSTAT_NUM_KINDS];
PgStat_ArchiverStats archiver;
PgStat_BgWriterStats bgwriter;
PgStat_CheckpointerStats checkpointer;
PgStat_IO io;
PgStat_SLRUStats slru[SLRU_NUM_ELEMENTS];
PgStat_WalStats wal;
MemoryContext context;
struct pgstat_snapshot_hash *stats;
} PgStat_Snapshot;
typedef struct PgStat_LocalState
{
PgStat_ShmemControl *shmem;
dsa_area *dsa;
dshash_table *shared_hash;
PgStat_Snapshot snapshot;
} PgStat_LocalState;
static inline void pgstat_begin_changecount_write(uint32 *cc);
static inline void pgstat_end_changecount_write(uint32 *cc);
static inline uint32 pgstat_begin_changecount_read(uint32 *cc);
static inline bool pgstat_end_changecount_read(uint32 *cc, uint32 cc_before);
static inline void pgstat_copy_changecounted_stats(void *dst, void *src, size_t len,
uint32 *cc);
static inline int pgstat_cmp_hash_key(const void *a, const void *b, size_t size, void *arg);
static inline uint32 pgstat_hash_hash_key(const void *d, size_t size, void *arg);
static inline size_t pgstat_get_entry_len(PgStat_Kind kind);
static inline void *pgstat_get_entry_data(PgStat_Kind kind, PgStatShared_Common *entry);
extern const PgStat_KindInfo *pgstat_get_kind_info(PgStat_Kind kind);
#ifdef USE_ASSERT_CHECKING
extern void pgstat_assert_is_up(void);
#else
#define pgstat_assert_is_up() ((void)true)
#endif
extern void pgstat_delete_pending_entry(PgStat_EntryRef *entry_ref);
extern PgStat_EntryRef *pgstat_prep_pending_entry(PgStat_Kind kind, Oid dboid, Oid objoid, bool *created_entry);
extern PgStat_EntryRef *pgstat_fetch_pending_entry(PgStat_Kind kind, Oid dboid, Oid objoid);
extern void *pgstat_fetch_entry(PgStat_Kind kind, Oid dboid, Oid objoid);
extern void pgstat_snapshot_fixed(PgStat_Kind kind);
extern void pgstat_archiver_reset_all_cb(TimestampTz ts);
extern void pgstat_archiver_snapshot_cb(void);
extern void pgstat_bgwriter_reset_all_cb(TimestampTz ts);
extern void pgstat_bgwriter_snapshot_cb(void);
extern void pgstat_checkpointer_reset_all_cb(TimestampTz ts);
extern void pgstat_checkpointer_snapshot_cb(void);
extern void pgstat_report_disconnect(Oid dboid);
extern void pgstat_update_dbstats(TimestampTz ts);
extern void AtEOXact_PgStat_Database(bool isCommit, bool parallel);
extern PgStat_StatDBEntry *pgstat_prep_database_pending(Oid dboid);
extern void pgstat_reset_database_timestamp(Oid dboid, TimestampTz ts);
extern bool pgstat_database_flush_cb(PgStat_EntryRef *entry_ref, bool nowait);
extern void pgstat_database_reset_timestamp_cb(PgStatShared_Common *header, TimestampTz ts);
extern bool pgstat_function_flush_cb(PgStat_EntryRef *entry_ref, bool nowait);
extern bool pgstat_flush_io(bool nowait);
extern void pgstat_io_reset_all_cb(TimestampTz ts);
extern void pgstat_io_snapshot_cb(void);
extern void AtEOXact_PgStat_Relations(PgStat_SubXactStatus *xact_state, bool isCommit);
extern void AtEOSubXact_PgStat_Relations(PgStat_SubXactStatus *xact_state, bool isCommit, int nestDepth);
extern void AtPrepare_PgStat_Relations(PgStat_SubXactStatus *xact_state);
extern void PostPrepare_PgStat_Relations(PgStat_SubXactStatus *xact_state);
extern bool pgstat_relation_flush_cb(PgStat_EntryRef *entry_ref, bool nowait);
extern void pgstat_relation_delete_pending_cb(PgStat_EntryRef *entry_ref);
extern void pgstat_replslot_reset_timestamp_cb(PgStatShared_Common *header, TimestampTz ts);
extern void pgstat_replslot_to_serialized_name_cb(const PgStat_HashKey *key, const PgStatShared_Common *header, NameData *name);
extern bool pgstat_replslot_from_serialized_name_cb(const NameData *name, PgStat_HashKey *key);
extern void pgstat_attach_shmem(void);
extern void pgstat_detach_shmem(void);
extern PgStat_EntryRef *pgstat_get_entry_ref(PgStat_Kind kind, Oid dboid, Oid objoid,
bool create, bool *created_entry);
extern bool pgstat_lock_entry(PgStat_EntryRef *entry_ref, bool nowait);
extern bool pgstat_lock_entry_shared(PgStat_EntryRef *entry_ref, bool nowait);
extern void pgstat_unlock_entry(PgStat_EntryRef *entry_ref);
extern bool pgstat_drop_entry(PgStat_Kind kind, Oid dboid, Oid objoid);
extern void pgstat_drop_all_entries(void);
extern PgStat_EntryRef *pgstat_get_entry_ref_locked(PgStat_Kind kind, Oid dboid, Oid objoid,
bool nowait);
extern void pgstat_reset_entry(PgStat_Kind kind, Oid dboid, Oid objoid, TimestampTz ts);
extern void pgstat_reset_entries_of_kind(PgStat_Kind kind, TimestampTz ts);
extern void pgstat_reset_matching_entries(bool (*do_reset) (PgStatShared_HashEntry *, Datum),
Datum match_data,
TimestampTz ts);
extern void pgstat_request_entry_refs_gc(void);
extern PgStatShared_Common *pgstat_init_entry(PgStat_Kind kind,
PgStatShared_HashEntry *shhashent);
extern bool pgstat_slru_flush(bool nowait);
extern void pgstat_slru_reset_all_cb(TimestampTz ts);
extern void pgstat_slru_snapshot_cb(void);
extern bool pgstat_flush_wal(bool nowait);
extern void pgstat_init_wal(void);
extern bool pgstat_have_pending_wal(void);
extern void pgstat_wal_reset_all_cb(TimestampTz ts);
extern void pgstat_wal_snapshot_cb(void);
extern bool pgstat_subscription_flush_cb(PgStat_EntryRef *entry_ref, bool nowait);
extern void pgstat_subscription_reset_timestamp_cb(PgStatShared_Common *header, TimestampTz ts);
extern PgStat_SubXactStatus *pgstat_get_xact_stack_level(int nest_level);
extern void pgstat_drop_transactional(PgStat_Kind kind, Oid dboid, Oid objoid);
extern void pgstat_create_transactional(PgStat_Kind kind, Oid dboid, Oid objoid);
extern PGDLLIMPORT PgStat_LocalState pgStatLocal;
extern PGDLLIMPORT bool have_iostats;
extern PGDLLIMPORT bool have_slrustats;
static inline void
pgstat_begin_changecount_write(uint32 *cc)
{
Assert((*cc & 1) == 0);
START_CRIT_SECTION();
(*cc)++;
pg_write_barrier();
}
static inline void
pgstat_end_changecount_write(uint32 *cc)
{
Assert((*cc & 1) == 1);
pg_write_barrier();
(*cc)++;
END_CRIT_SECTION();
}
static inline uint32
pgstat_begin_changecount_read(uint32 *cc)
{
uint32 before_cc = *cc;
CHECK_FOR_INTERRUPTS();
pg_read_barrier();
return before_cc;
}
static inline bool
pgstat_end_changecount_read(uint32 *cc, uint32 before_cc)
{
uint32 after_cc;
pg_read_barrier();
after_cc = *cc;
if (before_cc & 1)
return false;
return before_cc == after_cc;
}
static inline void
pgstat_copy_changecounted_stats(void *dst, void *src, size_t len,
uint32 *cc)
{
uint32 cc_before;
do
{
cc_before = pgstat_begin_changecount_read(cc);
memcpy(dst, src, len);
}
while (!pgstat_end_changecount_read(cc, cc_before));
}
static inline int
pgstat_cmp_hash_key(const void *a, const void *b, size_t size, void *arg)
{
Assert(size == sizeof(PgStat_HashKey) && arg == NULL);
return memcmp(a, b, sizeof(PgStat_HashKey));
}
static inline uint32
pgstat_hash_hash_key(const void *d, size_t size, void *arg)
{
const char *key = (const char *) d;
Assert(size == sizeof(PgStat_HashKey) && arg == NULL);
return fasthash32(key, size, 0);
}
static inline size_t
pgstat_get_entry_len(PgStat_Kind kind)
{
return pgstat_get_kind_info(kind)->shared_data_len;
}
static inline void *
pgstat_get_entry_data(PgStat_Kind kind, PgStatShared_Common *entry)
{
size_t off = pgstat_get_kind_info(kind)->shared_data_off;
Assert(off != 0 && off < PG_UINT32_MAX);
return ((char *) (entry)) + off;
}
#endif