21#define NUM_BUFFERCACHE_PAGES_MIN_ELEM 8
22#define NUM_BUFFERCACHE_PAGES_ELEM 9
23#define NUM_BUFFERCACHE_SUMMARY_ELEM 5
24#define NUM_BUFFERCACHE_USAGE_COUNTS_ELEM 4
25#define NUM_BUFFERCACHE_EVICT_ELEM 2
26#define NUM_BUFFERCACHE_EVICT_RELATION_ELEM 3
27#define NUM_BUFFERCACHE_EVICT_ALL_ELEM 3
29#define NUM_BUFFERCACHE_NUMA_ELEM 3
32 .
name =
"pg_buffercache",
141 elog(
ERROR,
"return type must be a row type");
145 elog(
ERROR,
"incorrect number of output arguments");
321 int pages_per_buffer;
328 elog(
ERROR,
"libnuma initialization failed or NUMA is not supported on this platform");
353 Assert((os_page_size % BLCKSZ == 0) || (BLCKSZ % os_page_size == 0));
362 endptr = (
char *)
TYPEALIGN(os_page_size,
364 os_page_count = (endptr - startptr) / os_page_size;
367 os_page_ptrs =
palloc0(
sizeof(
void *) * os_page_count);
368 os_page_status =
palloc(
sizeof(
uint64) * os_page_count);
372 for (
char *ptr = startptr; ptr < endptr; ptr += os_page_size)
374 os_page_ptrs[
idx++] = ptr;
384 "os_page_size=%zu",
NBuffers, os_page_count, os_page_size);
390 memset(os_page_status, 0xff,
sizeof(
int) * os_page_count);
394 elog(
ERROR,
"failed NUMA pages inquiry: %m");
407 elog(
ERROR,
"return type must be a row type");
410 elog(
ERROR,
"incorrect number of output arguments");
430 pages_per_buffer =
Max(1, BLCKSZ / os_page_size) + 1;
431 max_entries =
NBuffers * pages_per_buffer;
442 elog(
DEBUG1,
"NUMA: page-faulting the buffercache for proper NUMA readouts");
481 endptr_buff = buffptr + BLCKSZ;
483 Assert(startptr_buff < endptr_buff);
486 page_num = (startptr_buff - startptr) / os_page_size;
489 for (
char *ptr = startptr_buff; ptr < endptr_buff; ptr += os_page_size)
550 int32 buffers_used = 0;
551 int32 buffers_unused = 0;
552 int32 buffers_dirty = 0;
553 int32 buffers_pinned = 0;
554 int64 usagecount_total = 0;
557 elog(
ERROR,
"return type must be a row type");
588 memset(nulls, 0,
sizeof(nulls));
594 if (buffers_used != 0)
625 usage_counts[usage_count]++;
628 dirty[usage_count]++;
631 pinned[usage_count]++;
655 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
656 errmsg(
"must be superuser to use %s()",
676 elog(
ERROR,
"return type must be a row type");
707 int32 buffers_evicted = 0;
708 int32 buffers_flushed = 0;
709 int32 buffers_skipped = 0;
712 elog(
ERROR,
"return type must be a row type");
722 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
723 errmsg(
"relation uses local buffers, %s() is intended to be used for shared buffers only",
724 "pg_buffercache_evict_relation")));
754 int32 buffers_evicted = 0;
755 int32 buffers_flushed = 0;
756 int32 buffers_skipped = 0;
759 elog(
ERROR,
"return type must be a row type");
Datum idx(PG_FUNCTION_ARGS)
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
#define InvalidBlockNumber
static Datum values[MAXATTR]
#define BM_MAX_USAGE_COUNT
static ForkNumber BufTagGetForkNum(const BufferTag *tag)
static void UnlockBufHdr(BufferDesc *desc, uint32 buf_state)
static RelFileNumber BufTagGetRelNumber(const BufferTag *tag)
#define BUF_STATE_GET_USAGECOUNT(state)
#define BUF_STATE_GET_REFCOUNT(state)
static BufferDesc * GetBufferDescriptor(uint32 id)
static Buffer BufferDescriptorGetBuffer(const BufferDesc *bdesc)
void EvictAllUnpinnedBuffers(int32 *buffers_evicted, int32 *buffers_flushed, int32 *buffers_skipped)
void EvictRelUnpinnedBuffers(Relation rel, int32 *buffers_evicted, int32 *buffers_flushed, int32 *buffers_skipped)
bool EvictUnpinnedBuffer(Buffer buf, bool *buffer_flushed)
uint32 LockBufHdr(BufferDesc *desc)
static Block BufferGetBlock(Buffer buffer)
#define pg_attribute_unused()
#define TYPEALIGN(ALIGNVAL, LEN)
#define TYPEALIGN_DOWN(ALIGNVAL, LEN)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Datum Int64GetDatum(int64 X)
Datum Float8GetDatum(float8 X)
#define PG_GETARG_INT32(n)
#define PG_RETURN_DATUM(x)
void InitMaterializedSRF(FunctionCallInfo fcinfo, bits32 flags)
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
#define SRF_IS_FIRSTCALL()
#define SRF_PERCALL_SETUP()
#define SRF_RETURN_NEXT(_funcctx, _result)
#define SRF_FIRSTCALL_INIT()
static Datum HeapTupleGetDatum(const HeapTupleData *tuple)
#define SRF_RETURN_DONE(_funcctx)
Assert(PointerIsAligned(start, uint64))
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
void * palloc0(Size size)
MemoryContext CurrentMemoryContext
void * MemoryContextAllocHuge(MemoryContext context, Size size)
#define CHECK_FOR_INTERRUPTS()
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
PG_MODULE_MAGIC_EXT(.name="pg_buffercache",.version=PG_VERSION)
Datum pg_buffercache_evict_relation(PG_FUNCTION_ARGS)
#define NUM_BUFFERCACHE_USAGE_COUNTS_ELEM
Datum pg_buffercache_evict(PG_FUNCTION_ARGS)
Datum pg_buffercache_summary(PG_FUNCTION_ARGS)
static void pg_buffercache_superuser_check(char *func_name)
PG_FUNCTION_INFO_V1(pg_buffercache_pages)
Datum pg_buffercache_usage_counts(PG_FUNCTION_ARGS)
#define NUM_BUFFERCACHE_SUMMARY_ELEM
Datum pg_buffercache_pages(PG_FUNCTION_ARGS)
#define NUM_BUFFERCACHE_EVICT_ELEM
#define NUM_BUFFERCACHE_PAGES_MIN_ELEM
#define NUM_BUFFERCACHE_EVICT_ALL_ELEM
Datum pg_buffercache_evict_all(PG_FUNCTION_ARGS)
#define NUM_BUFFERCACHE_PAGES_ELEM
Datum pg_buffercache_numa_pages(PG_FUNCTION_ARGS)
static bool firstNumaTouch
#define NUM_BUFFERCACHE_NUMA_ELEM
#define NUM_BUFFERCACHE_EVICT_RELATION_ELEM
#define pg_numa_touch_mem_if_required(ro_volatile_var, ptr)
PGDLLIMPORT int pg_numa_query_pages(int pid, unsigned long count, void **pages, int *status)
PGDLLIMPORT int pg_numa_init(void)
static Datum Int16GetDatum(int16 X)
static Datum BoolGetDatum(bool X)
static Datum ObjectIdGetDatum(Oid X)
static Datum Int32GetDatum(int32 X)
#define RelationUsesLocalBuffers(relation)
Size pg_get_shmem_pagesize(void)
void relation_close(Relation relation, LOCKMODE lockmode)
Relation relation_open(Oid relationId, LOCKMODE lockmode)
BufferCacheNumaRec * record
BufferCachePagesRec * record
RelFileNumber relfilenumber
MemoryContext multi_call_memory_ctx
TupleDesc CreateTemplateTupleDesc(int natts)
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, const Datum *values, const bool *isnull)