67 #define BufHdrGetBlock(bufHdr) ((Block) (BufferBlocks + ((Size) (bufHdr)->buf_id) * BLCKSZ))
68 #define BufferGetLSN(bufHdr) (PageGetLSN(BufHdrGetBlock(bufHdr)))
71 #define LocalBufHdrGetBlock(bufHdr) \
72 LocalBufferBlockPointers[-((bufHdr)->buf_id + 2)]
75 #define BUF_WRITTEN 0x01
76 #define BUF_REUSABLE 0x02
78 #define RELS_BSEARCH_THRESHOLD 20
86 #define BUF_DROP_FULL_SCAN_THRESHOLD (uint64) (NBuffers / 32)
95 #define REFCOUNT_ARRAY_ENTRIES 8
236 .
name =
"buffer pin",
397 free->refcount =
res->refcount;
473 #define BufferIsPinned(bufnum) \
475 !BufferIsValid(bufnum) ? \
478 BufferIsLocal(bufnum) ? \
479 (LocalRefCount[-(bufnum) - 1] > 0) \
481 (GetPrivateRefCount(bufnum) > 0) \
511 static int SyncOneBuffer(
int buf_id,
bool skip_recently_used,
516 uint32 set_flag_bits,
bool forget_owner);
648 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
649 errmsg(
"cannot access temporary tables of other sessions")));
675 bool have_private_ref;
685 int b = -recent_buffer - 1;
710 if (have_private_ref)
722 if (have_private_ref)
733 if (!have_private_ref)
804 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
805 errmsg(
"cannot access temporary tables of other sessions")));
812 forkNum, blockNum,
mode, strategy);
836 permanent ? RELPERSISTENCE_PERMANENT : RELPERSISTENCE_UNLOGGED,
889 if (bmr.
smgr == NULL)
897 buffers, extended_by);
925 if (bmr.
smgr == NULL)
981 num_pages, extend_to,
982 buffers, &extended_by);
989 if (first_block +
i != extend_to - 1)
1004 Assert(extended_by == 0);
1006 fork, extend_to - 1,
mode, strategy);
1061 char smgr_persistence,
1081 persistence = rel->
rd_rel->relpersistence;
1082 else if (smgr_persistence == 0)
1083 persistence = RELPERSISTENCE_PERMANENT;
1085 persistence = smgr_persistence;
1087 if (persistence == RELPERSISTENCE_TEMP)
1098 TRACE_POSTGRESQL_BUFFER_READ_START(forkNum, blockNum,
1104 if (persistence == RELPERSISTENCE_TEMP)
1112 bufHdr =
BufferAlloc(smgr, persistence, forkNum, blockNum,
1113 strategy, foundPtr, io_context);
1135 TRACE_POSTGRESQL_BUFFER_READ_DONE(forkNum, blockNum,
1187 forkNum, blockNum, strategy, &found);
1196 operation.
smgr = smgr;
1197 operation.
rel = rel;
1217 int actual_nblocks = *nblocks;
1218 int io_buffers_len = 0;
1223 for (
int i = 0;
i < actual_nblocks; ++
i)
1243 actual_nblocks =
i + 1;
1252 *nblocks = actual_nblocks;
1254 if (
likely(io_buffers_len == 0))
1260 operation->
flags = flags;
1261 operation->
nblocks = actual_nblocks;
1372 buffers = &operation->
buffers[0];
1376 persistence = operation->
rel
1377 ? operation->
rel->
rd_rel->relpersistence
1378 : RELPERSISTENCE_PERMANENT;
1379 if (persistence == RELPERSISTENCE_TEMP)
1398 if (persistence == RELPERSISTENCE_TEMP)
1403 for (
int i = 0;
i < nblocks; ++
i)
1423 TRACE_POSTGRESQL_BUFFER_READ_DONE(forknum, blocknum +
i,
1433 io_buffers[0] = buffers[
i];
1435 io_first_block = blocknum +
i;
1445 while ((
i + 1) < nblocks &&
1452 io_buffers[io_buffers_len] = buffers[++
i];
1457 smgrreadv(operation->
smgr, forknum, io_first_block, io_pages, io_buffers_len);
1462 for (
int j = 0;
j < io_buffers_len; ++
j)
1467 if (persistence == RELPERSISTENCE_TEMP)
1486 errmsg(
"invalid page in block %u of relation %s; zeroing out page",
1489 memset(bufBlock, 0, BLCKSZ);
1494 errmsg(
"invalid page in block %u of relation %s",
1500 if (persistence == RELPERSISTENCE_TEMP)
1514 TRACE_POSTGRESQL_BUFFER_READ_DONE(forknum, io_first_block +
j,
1555 LWLock *newPartitionLock;
1556 int existing_buf_id;
1575 if (existing_buf_id >= 0)
1628 if (existing_buf_id >= 0)
1655 valid =
PinBuffer(existing_buf_hdr, strategy);
1672 return existing_buf_hdr;
1678 victim_buf_state =
LockBufHdr(victim_buf_hdr);
1684 victim_buf_hdr->
tag = newTag;
1693 if (relpersistence == RELPERSISTENCE_PERMANENT || forkNum ==
INIT_FORKNUM)
1705 return victim_buf_hdr;
1730 LWLock *oldPartitionLock;
1783 elog(
ERROR,
"buffer is pinned in InvalidateBuffer");
1972 if (strategy != NULL)
2033 #ifdef USE_ASSERT_CHECKING
2061 int max_proportional_pins;
2063 if (*additional_pins <= 1)
2067 max_proportional_pins =
NBuffers / max_backends;
2077 if (max_proportional_pins <= 0)
2078 max_proportional_pins = 1;
2080 if (*additional_pins > max_proportional_pins)
2081 *additional_pins = max_proportional_pins;
2100 TRACE_POSTGRESQL_BUFFER_EXTEND_START(fork,
2109 extend_by, extend_upto,
2110 buffers, &extend_by);
2113 extend_by, extend_upto,
2114 buffers, &extend_by);
2115 *extended_by = extend_by;
2117 TRACE_POSTGRESQL_BUFFER_EXTEND_DONE(fork,
2166 MemSet((
char *) buf_block, 0, BLCKSZ);
2199 uint32 orig_extend_by = extend_by;
2201 if (first_block > extend_upto)
2203 else if ((uint64) first_block + extend_by > extend_upto)
2204 extend_by = extend_upto - first_block;
2206 for (
uint32 i = extend_by;
i < orig_extend_by;
i++)
2222 *extended_by = extend_by;
2230 (
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
2231 errmsg(
"cannot extend relation %s beyond %u blocks",
2243 Buffer victim_buf = buffers[
i];
2276 if (existing_id >= 0)
2286 valid =
PinBuffer(existing_hdr, strategy);
2302 (
errmsg(
"unexpected data beyond EOF in block %u of relation %s",
2304 errhint(
"This has been seen to occur with buggy kernels; consider updating your system.")));
2334 victim_buf_hdr->
tag = tag;
2374 io_start, extend_by);
2388 if (first_block +
i + 1 == extend_upto)
2400 *extended_by = extend_by;
2501 buf_state = old_buf_state;
2619 buf_state = old_buf_state;
2624 if (strategy == NULL)
2643 result = (buf_state &
BM_VALID) != 0;
2799 buf_state = old_buf_state;
2824 int wait_backend_pgprocno =
buf->wait_backend_pgprocno;
2837 #define ST_SORT sort_checkpoint_bufferids
2838 #define ST_ELEMENT_TYPE CkptSortItem
2839 #define ST_COMPARE(a, b) ckpt_buforder_comparator(a, b)
2840 #define ST_SCOPE static
2896 for (buf_id = 0; buf_id <
NBuffers; buf_id++)
2906 if ((buf_state & mask) == mask)
2927 if (num_to_scan == 0)
2932 TRACE_POSTGRESQL_BUFFER_SYNC_START(
NBuffers, num_to_scan);
2950 for (
i = 0;
i < num_to_scan;
i++)
2961 if (last_tsid ==
InvalidOid || last_tsid != cur_tsid)
2973 if (per_ts_stat == NULL)
2978 s = &per_ts_stat[num_spaces - 1];
2979 memset(s, 0,
sizeof(*s));
2994 last_tsid = cur_tsid;
2998 s = &per_ts_stat[num_spaces - 1];
3019 for (
i = 0;
i < num_spaces;
i++)
3067 TRACE_POSTGRESQL_BUFFER_SYNC_WRITTEN(buf_id);
3116 TRACE_POSTGRESQL_BUFFER_SYNC_DONE(
NBuffers, num_written, num_to_scan);
3134 int strategy_buf_id;
3142 static bool saved_info_valid =
false;
3143 static int prev_strategy_buf_id;
3144 static uint32 prev_strategy_passes;
3145 static int next_to_clean;
3146 static uint32 next_passes;
3149 static float smoothed_alloc = 0;
3150 static float smoothed_density = 10.0;
3153 float smoothing_samples = 16;
3154 float scan_whole_pool_milliseconds = 120000.0;
3157 long strategy_delta;
3160 float scans_per_alloc;
3161 int reusable_buffers_est;
3162 int upcoming_alloc_est;
3163 int min_scan_buffers;
3168 int reusable_buffers;
3171 long new_strategy_delta;
3190 saved_info_valid =
false;
3202 if (saved_info_valid)
3204 int32 passes_delta = strategy_passes - prev_strategy_passes;
3206 strategy_delta = strategy_buf_id - prev_strategy_buf_id;
3207 strategy_delta += (long) passes_delta *
NBuffers;
3209 Assert(strategy_delta >= 0);
3211 if ((
int32) (next_passes - strategy_passes) > 0)
3214 bufs_to_lap = strategy_buf_id - next_to_clean;
3216 elog(
DEBUG2,
"bgwriter ahead: bgw %u-%u strategy %u-%u delta=%ld lap=%d",
3217 next_passes, next_to_clean,
3218 strategy_passes, strategy_buf_id,
3219 strategy_delta, bufs_to_lap);
3222 else if (next_passes == strategy_passes &&
3223 next_to_clean >= strategy_buf_id)
3226 bufs_to_lap =
NBuffers - (next_to_clean - strategy_buf_id);
3228 elog(
DEBUG2,
"bgwriter ahead: bgw %u-%u strategy %u-%u delta=%ld lap=%d",
3229 next_passes, next_to_clean,
3230 strategy_passes, strategy_buf_id,
3231 strategy_delta, bufs_to_lap);
3241 elog(
DEBUG2,
"bgwriter behind: bgw %u-%u strategy %u-%u delta=%ld",
3242 next_passes, next_to_clean,
3243 strategy_passes, strategy_buf_id,
3246 next_to_clean = strategy_buf_id;
3247 next_passes = strategy_passes;
3258 elog(
DEBUG2,
"bgwriter initializing: strategy %u-%u",
3259 strategy_passes, strategy_buf_id);
3262 next_to_clean = strategy_buf_id;
3263 next_passes = strategy_passes;
3268 prev_strategy_buf_id = strategy_buf_id;
3269 prev_strategy_passes = strategy_passes;
3270 saved_info_valid =
true;
3278 if (strategy_delta > 0 && recent_alloc > 0)
3280 scans_per_alloc = (float) strategy_delta / (
float) recent_alloc;
3281 smoothed_density += (scans_per_alloc - smoothed_density) /
3290 bufs_ahead =
NBuffers - bufs_to_lap;
3291 reusable_buffers_est = (float) bufs_ahead / smoothed_density;
3298 if (smoothed_alloc <= (
float) recent_alloc)
3299 smoothed_alloc = recent_alloc;
3301 smoothed_alloc += ((float) recent_alloc - smoothed_alloc) /
3315 if (upcoming_alloc_est == 0)
3330 if (upcoming_alloc_est < (min_scan_buffers + reusable_buffers_est))
3333 elog(
DEBUG2,
"bgwriter: alloc_est=%d too small, using min=%d + reusable_est=%d",
3334 upcoming_alloc_est, min_scan_buffers, reusable_buffers_est);
3336 upcoming_alloc_est = min_scan_buffers + reusable_buffers_est;
3346 num_to_scan = bufs_to_lap;
3348 reusable_buffers = reusable_buffers_est;
3351 while (num_to_scan > 0 && reusable_buffers < upcoming_alloc_est)
3379 elog(
DEBUG1,
"bgwriter: recent_alloc=%u smoothed=%.2f delta=%ld ahead=%d density=%.2f reusable_est=%d upcoming_est=%d scanned=%d wrote=%d reusable=%d",
3380 recent_alloc, smoothed_alloc, strategy_delta, bufs_ahead,
3381 smoothed_density, reusable_buffers_est, upcoming_alloc_est,
3382 bufs_to_lap - num_to_scan,
3384 reusable_buffers - reusable_buffers_est);
3395 new_strategy_delta = bufs_to_lap - num_to_scan;
3396 new_recent_alloc = reusable_buffers - reusable_buffers_est;
3397 if (new_strategy_delta > 0 && new_recent_alloc > 0)
3399 scans_per_alloc = (float) new_strategy_delta / (
float) new_recent_alloc;
3400 smoothed_density += (scans_per_alloc - smoothed_density) /
3404 elog(
DEBUG2,
"bgwriter: cleaner density alloc=%u scan=%ld density=%.2f new smoothed=%.2f",
3405 new_recent_alloc, new_strategy_delta,
3406 scans_per_alloc, smoothed_density);
3411 return (bufs_to_lap == 0 && recent_alloc == 0);
3456 else if (skip_recently_used)
3564 #ifdef USE_ASSERT_CHECKING
3565 int RefCountErrors = 0;
3600 Assert(RefCountErrors == 0);
3636 result =
psprintf(
"[%03d] (rel=%s, blockNum=%u, flags=0x%x, refcount=%u %d)",
3747 errcallback.
arg = (
void *)
buf;
3868 if (RELKIND_HAS_TABLE_AM(relation->
rd_rel->relkind))
3880 return (szbytes + (BLCKSZ - 1)) / BLCKSZ;
3882 else if (RELKIND_HAS_STORAGE(relation->
rd_rel->relkind))
3981 uint64 nBlocksToInvalidate = 0;
3990 for (
j = 0;
j < nforks;
j++)
4019 for (
i = 0;
i < nforks;
i++)
4031 nBlocksToInvalidate += (nForkBlock[
i] - firstDelBlock[
i]);
4041 for (
j = 0;
j < nforks;
j++)
4043 nForkBlock[
j], firstDelBlock[
j]);
4073 for (
j = 0;
j < nforks;
j++)
4103 uint64 nBlocksToInvalidate = 0;
4114 for (
i = 0;
i < nlocators;
i++)
4122 rels[n++] = smgr_reln[
i];
4146 for (
i = 0;
i < n && cached;
i++)
4163 nBlocksToInvalidate += block[
i][
j];
4173 for (
i = 0;
i < n;
i++)
4194 for (
i = 0;
i < n;
i++)
4195 locators[
i] = rels[
i]->smgr_rlocator.locator;
4224 for (
j = 0;
j < n;
j++)
4228 rlocator = &locators[
j];
4238 rlocator = bsearch((
const void *) &(locator),
4244 if (rlocator == NULL)
4274 for (curBlock = firstDelBlock; curBlock < nForkBlock; curBlock++)
4278 LWLock *bufPartitionLock;
4367 PrintBufferDescs(
void)
4378 "[%02d] (freeNext=%d, rel=%s, "
4379 "blockNum=%u, flags=0x%x, refcount=%u %d)",
4383 buf->tag.blockNum,
buf->flags,
4391 PrintPinnedBufs(
void)
4404 "[%02d] (freeNext=%d, rel=%s, "
4405 "blockNum=%u, flags=0x%x, refcount=%u %d)",
4409 buf->tag.blockNum,
buf->flags,
4460 errcallback.
arg = (
void *) bufHdr;
4545 for (
i = 0;
i < nrels;
i++)
4550 srels[
i].
srel = smgrs[
i];
4578 for (
j = 0;
j < nrels;
j++)
4582 srelent = &srels[
j];
4592 srelent = bsearch((
const void *) &(rlocator),
4598 if (srelent == NULL)
4667 memset(
buf.data, 0, BLCKSZ);
4676 for (blkno = 0; blkno < nblocks; blkno++)
4695 memcpy(dstPage, srcPage, BLCKSZ);
4727 char relpersistence;
4732 relpersistence = permanent ?
4733 RELPERSISTENCE_PERMANENT : RELPERSISTENCE_UNLOGGED;
4949 bool dirtied =
false;
4950 bool delayChkptFlags =
false;
5002 delayChkptFlags =
true;
5034 if (delayChkptFlags)
5137 elog(
ERROR,
"incorrect local pin count: %d",
5143 elog(
ERROR,
"incorrect local pin count: %d",
5170 bool logged_recovery_conflict =
false;
5202 if (logged_recovery_conflict)
5220 elog(
ERROR,
"multiple backends attempting to wait for pincount 1");
5246 if (waitStart != 0 && !logged_recovery_conflict)
5254 waitStart,
now, NULL,
true);
5255 logged_recovery_conflict =
true;
5555 buf_state |= set_flag_bits;
5607 errmsg(
"could not write block %u of %s",
5609 errdetail(
"Multiple failures --- write error might be permanent.")));
5631 errcontext(
"writing block %u of relation %s",
5651 errcontext(
"writing block %u of relation %s",
5779 if (
a->tsId <
b->tsId)
5781 else if (
a->tsId >
b->tsId)
5784 if (
a->relNumber <
b->relNumber)
5786 else if (
a->relNumber >
b->relNumber)
5789 else if (
a->forkNum <
b->forkNum)
5791 else if (
a->forkNum >
b->forkNum)
5794 else if (
a->blockNum <
b->blockNum)
5796 else if (
a->blockNum >
b->blockNum)
5834 context->max_pending = max_pending;
5860 pending->
tag = *tag;
5872 #define ST_SORT sort_pending_writebacks
5873 #define ST_ELEMENT_TYPE PendingWriteback
5874 #define ST_COMPARE(a, b) buffertag_comparator(&a->tag, &b->tag)
5875 #define ST_SCOPE static
5927 for (ahead = 0;
i + ahead + 1 < wb_context->
nr_pending; ahead++)
5939 if (
cur->tag.blockNum ==
next->tag.blockNum)
5943 if (
cur->tag.blockNum + 1 !=
next->tag.blockNum)
static bool pg_atomic_compare_exchange_u32(volatile pg_atomic_uint32 *ptr, uint32 *expected, uint32 newval)
static uint32 pg_atomic_fetch_or_u32(volatile pg_atomic_uint32 *ptr, uint32 or_)
static void pg_atomic_unlocked_write_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
bool TimestampDifferenceExceeds(TimestampTz start_time, TimestampTz stop_time, int msec)
TimestampTz GetCurrentTimestamp(void)
Datum now(PG_FUNCTION_ARGS)
void binaryheap_build(binaryheap *heap)
void binaryheap_replace_first(binaryheap *heap, bh_node_type d)
bh_node_type binaryheap_first(binaryheap *heap)
bh_node_type binaryheap_remove_first(binaryheap *heap)
binaryheap * binaryheap_allocate(int capacity, binaryheap_comparator compare, void *arg)
void binaryheap_free(binaryheap *heap)
void binaryheap_add_unordered(binaryheap *heap, bh_node_type d)
#define binaryheap_empty(h)
#define InvalidBlockNumber
static bool BlockNumberIsValid(BlockNumber blockNumber)
#define BufferIsLocal(buffer)
CkptSortItem * CkptBufferIds
WritebackContext BackendWritebackContext
#define BM_MAX_USAGE_COUNT
static void InitBufferTag(BufferTag *tag, const RelFileLocator *rlocator, ForkNumber forkNum, BlockNumber blockNum)
#define BUF_USAGECOUNT_MASK
static ForkNumber BufTagGetForkNum(const BufferTag *tag)
static BufferDesc * GetLocalBufferDescriptor(uint32 id)
static BufferDesc * GetBufferDescriptor(uint32 id)
static void UnlockBufHdr(BufferDesc *desc, uint32 buf_state)
static bool BufferTagsEqual(const BufferTag *tag1, const BufferTag *tag2)
static RelFileNumber BufTagGetRelNumber(const BufferTag *tag)
static bool BufTagMatchesRelFileLocator(const BufferTag *tag, const RelFileLocator *rlocator)
static LWLock * BufMappingPartitionLock(uint32 hashcode)
#define BM_PIN_COUNT_WAITER
static void ResourceOwnerRememberBufferIO(ResourceOwner owner, Buffer buffer)
#define BUF_STATE_GET_USAGECOUNT(state)
static void ResourceOwnerForgetBufferIO(ResourceOwner owner, Buffer buffer)
#define BM_IO_IN_PROGRESS
static void ClearBufferTag(BufferTag *tag)
static void ResourceOwnerRememberBuffer(ResourceOwner owner, Buffer buffer)
static void ResourceOwnerForgetBuffer(ResourceOwner owner, Buffer buffer)
static ConditionVariable * BufferDescriptorGetIOCV(const BufferDesc *bdesc)
#define BUF_USAGECOUNT_ONE
#define BUF_STATE_GET_REFCOUNT(state)
static RelFileLocator BufTagGetRelFileLocator(const BufferTag *tag)
static Buffer BufferDescriptorGetBuffer(const BufferDesc *bdesc)
#define BM_CHECKPOINT_NEEDED
static LWLock * BufferDescriptorGetContentLock(const BufferDesc *bdesc)
void BufTableDelete(BufferTag *tagPtr, uint32 hashcode)
int BufTableLookup(BufferTag *tagPtr, uint32 hashcode)
uint32 BufTableHashCode(BufferTag *tagPtr)
int BufTableInsert(BufferTag *tagPtr, uint32 hashcode, int buf_id)
void CheckBufferIsPinnedOnce(Buffer buffer)
void FlushRelationsAllBuffers(SMgrRelation *smgrs, int nrels)
void IncrBufferRefCount(Buffer buffer)
void DropDatabaseBuffers(Oid dbid)
static int ckpt_buforder_comparator(const CkptSortItem *a, const CkptSortItem *b)
bool BufferIsExclusiveLocked(Buffer buffer)
const ResourceOwnerDesc buffer_pin_resowner_desc
BlockNumber BufferGetBlockNumber(Buffer buffer)
static PrivateRefCountEntry * NewPrivateRefCountEntry(Buffer buffer)
void DropRelationBuffers(SMgrRelation smgr_reln, ForkNumber *forkNum, int nforks, BlockNumber *firstDelBlock)
Buffer ReleaseAndReadBuffer(Buffer buffer, Relation relation, BlockNumber blockNum)
static pg_attribute_always_inline Buffer PinBufferForBlock(Relation rel, SMgrRelation smgr, char smgr_persistence, ForkNumber forkNum, BlockNumber blockNum, BufferAccessStrategy strategy, bool *foundPtr)
PrefetchBufferResult PrefetchBuffer(Relation reln, ForkNumber forkNum, BlockNumber blockNum)
static uint32 PrivateRefCountClock
static void FlushBuffer(BufferDesc *buf, SMgrRelation reln, IOObject io_object, IOContext io_context)
static void ResOwnerReleaseBufferIO(Datum res)
bool StartReadBuffers(ReadBuffersOperation *operation, Buffer *buffers, BlockNumber blockNum, int *nblocks, int flags)
static bool WaitReadBuffersCanStartIO(Buffer buffer, bool nowait)
static bool PinBuffer(BufferDesc *buf, BufferAccessStrategy strategy)
const ResourceOwnerDesc buffer_io_resowner_desc
#define BUF_DROP_FULL_SCAN_THRESHOLD
static void PinBuffer_Locked(BufferDesc *buf)
static uint32 WaitBufHdrUnlocked(BufferDesc *buf)
static int buffertag_comparator(const BufferTag *ba, const BufferTag *bb)
#define LocalBufHdrGetBlock(bufHdr)
bool IsBufferCleanupOK(Buffer buffer)
#define BufferGetLSN(bufHdr)
static void TerminateBufferIO(BufferDesc *buf, bool clear_dirty, uint32 set_flag_bits, bool forget_owner)
static char * ResOwnerPrintBufferIO(Datum res)
Buffer ExtendBufferedRel(BufferManagerRelation bmr, ForkNumber forkNum, BufferAccessStrategy strategy, uint32 flags)
void AtEOXact_Buffers(bool isCommit)
char * DebugPrintBufferRefcount(Buffer buffer)
static void AbortBufferIO(Buffer buffer)
BlockNumber ExtendBufferedRelBy(BufferManagerRelation bmr, ForkNumber fork, BufferAccessStrategy strategy, uint32 flags, uint32 extend_by, Buffer *buffers, uint32 *extended_by)
static Buffer ReadBuffer_common(Relation rel, SMgrRelation smgr, char smgr_persistence, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
static BufferDesc * BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum, BlockNumber blockNum, BufferAccessStrategy strategy, bool *foundPtr, IOContext io_context)
static void CheckForBufferLeaks(void)
void CreateAndCopyRelationData(RelFileLocator src_rlocator, RelFileLocator dst_rlocator, bool permanent)
void DropRelationsAllBuffers(SMgrRelation *smgr_reln, int nlocators)
static int rlocator_comparator(const void *p1, const void *p2)
Buffer ExtendBufferedRelTo(BufferManagerRelation bmr, ForkNumber fork, BufferAccessStrategy strategy, uint32 flags, BlockNumber extend_to, ReadBufferMode mode)
struct SMgrSortArray SMgrSortArray
static bool InvalidateVictimBuffer(BufferDesc *buf_hdr)
static void AtProcExit_Buffers(int code, Datum arg)
static int ts_ckpt_progress_comparator(Datum a, Datum b, void *arg)
void BufferGetTag(Buffer buffer, RelFileLocator *rlocator, ForkNumber *forknum, BlockNumber *blknum)
#define BufHdrGetBlock(bufHdr)
static void local_buffer_write_error_callback(void *arg)
static void BufferSync(int flags)
static char * ResOwnerPrintBufferPin(Datum res)
void CheckPointBuffers(int flags)
bool BufferIsDirty(Buffer buffer)
static BlockNumber ExtendBufferedRelShared(BufferManagerRelation bmr, ForkNumber fork, BufferAccessStrategy strategy, uint32 flags, uint32 extend_by, BlockNumber extend_upto, Buffer *buffers, uint32 *extended_by)
bool BgBufferSync(WritebackContext *wb_context)
bool BufferIsPermanent(Buffer buffer)
#define REFCOUNT_ARRAY_ENTRIES
PrefetchBufferResult PrefetchSharedBuffer(SMgrRelation smgr_reln, ForkNumber forkNum, BlockNumber blockNum)
static Buffer GetVictimBuffer(BufferAccessStrategy strategy, IOContext io_context)
bool ConditionalLockBuffer(Buffer buffer)
BlockNumber RelationGetNumberOfBlocksInFork(Relation relation, ForkNumber forkNum)
void ReleaseBuffer(Buffer buffer)
static void FindAndDropRelationBuffers(RelFileLocator rlocator, ForkNumber forkNum, BlockNumber nForkBlock, BlockNumber firstDelBlock)
XLogRecPtr BufferGetLSNAtomic(Buffer buffer)
bool HoldingBufferPinThatDelaysRecovery(void)
int checkpoint_flush_after
void UnlockReleaseBuffer(Buffer buffer)
static void UnpinBufferNoOwner(BufferDesc *buf)
static void shared_buffer_write_error_callback(void *arg)
void ScheduleBufferTagForWriteback(WritebackContext *wb_context, IOContext io_context, BufferTag *tag)
void WaitReadBuffers(ReadBuffersOperation *operation)
void WritebackContextInit(WritebackContext *context, int *max_pending)
void MarkBufferDirty(Buffer buffer)
void InitBufferPoolAccess(void)
static pg_attribute_always_inline bool StartReadBuffersImpl(ReadBuffersOperation *operation, Buffer *buffers, BlockNumber blockNum, int *nblocks, int flags)
#define BufferIsPinned(bufnum)
double bgwriter_lru_multiplier
void LimitAdditionalPins(uint32 *additional_pins)
static void ReservePrivateRefCountEntry(void)
static BufferDesc * PinCountWaitBuf
static int32 GetPrivateRefCount(Buffer buffer)
static void ZeroBuffer(Buffer buffer, ReadBufferMode mode)
static BlockNumber ExtendBufferedRelCommon(BufferManagerRelation bmr, ForkNumber fork, BufferAccessStrategy strategy, uint32 flags, uint32 extend_by, BlockNumber extend_upto, Buffer *buffers, uint32 *extended_by)
void LockBufferForCleanup(Buffer buffer)
void LockBuffer(Buffer buffer, int mode)
static PrivateRefCountEntry * ReservedRefCountEntry
void MarkBufferDirtyHint(Buffer buffer, bool buffer_std)
void FlushRelationBuffers(Relation rel)
void IssuePendingWritebacks(WritebackContext *wb_context, IOContext io_context)
static void ForgetPrivateRefCountEntry(PrivateRefCountEntry *ref)
Buffer ReadBufferWithoutRelcache(RelFileLocator rlocator, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy, bool permanent)
bool ReadRecentBuffer(RelFileLocator rlocator, ForkNumber forkNum, BlockNumber blockNum, Buffer recent_buffer)
#define RELS_BSEARCH_THRESHOLD
int maintenance_io_concurrency
static void UnpinBuffer(BufferDesc *buf)
void FlushDatabaseBuffers(Oid dbid)
static void InvalidateBuffer(BufferDesc *buf)
static void RelationCopyStorageUsingBuffer(RelFileLocator srclocator, RelFileLocator dstlocator, ForkNumber forkNum, bool permanent)
int effective_io_concurrency
static PrivateRefCountEntry * GetPrivateRefCountEntry(Buffer buffer, bool do_move)
bool EvictUnpinnedBuffer(Buffer buf)
struct PrivateRefCountEntry PrivateRefCountEntry
struct CkptTsStatus CkptTsStatus
bool StartReadBuffer(ReadBuffersOperation *operation, Buffer *buffer, BlockNumber blocknum, int flags)
Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
uint32 LockBufHdr(BufferDesc *desc)
static void ResOwnerReleaseBufferPin(Datum res)
static struct PrivateRefCountEntry PrivateRefCountArray[REFCOUNT_ARRAY_ENTRIES]
static int SyncOneBuffer(int buf_id, bool skip_recently_used, WritebackContext *wb_context)
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
static HTAB * PrivateRefCountHash
static int32 PrivateRefCountOverflowed
bool ConditionalLockBufferForCleanup(Buffer buffer)
int bgwriter_lru_maxpages
static void WaitIO(BufferDesc *buf)
static bool StartBufferIO(BufferDesc *buf, bool forInput, bool nowait)
void FlushOneBuffer(Buffer buffer)
#define BUFFER_LOCK_UNLOCK
#define BUFFER_LOCK_SHARE
static Page BufferGetPage(Buffer buffer)
#define DEFAULT_IO_COMBINE_LIMIT
static Block BufferGetBlock(Buffer buffer)
#define MAX_IO_COMBINE_LIMIT
#define DEFAULT_EFFECTIVE_IO_CONCURRENCY
@ READ_BUFFERS_ZERO_ON_ERROR
@ READ_BUFFERS_ISSUE_ADVICE
#define DEFAULT_MAINTENANCE_IO_CONCURRENCY
@ EB_CREATE_FORK_IF_NEEDED
#define BUFFER_LOCK_EXCLUSIVE
@ RBM_ZERO_AND_CLEANUP_LOCK
static bool BufferIsValid(Buffer bufnum)
bool PageIsVerifiedExtended(Page page, BlockNumber blkno, int flags)
void PageSetChecksumInplace(Page page, BlockNumber blkno)
char * PageSetChecksumCopy(Page page, BlockNumber blkno)
static bool PageIsNew(Page page)
static void PageSetLSN(Page page, XLogRecPtr lsn)
static XLogRecPtr PageGetLSN(Page page)
#define Assert(condition)
#define pg_attribute_always_inline
#define MemSet(start, val, len)
void CheckpointWriteDelay(int flags, double progress)
bool ConditionVariableCancelSleep(void)
void ConditionVariableBroadcast(ConditionVariable *cv)
void ConditionVariablePrepareToSleep(ConditionVariable *cv)
void ConditionVariableSleep(ConditionVariable *cv, uint32 wait_event_info)
static void PGresult const char * p2
static void PGresult * res
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
void * hash_seq_search(HASH_SEQ_STATUS *status)
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
int errdetail(const char *fmt,...)
ErrorContextCallback * error_context_stack
int errhint(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
int StrategySyncStart(uint32 *complete_passes, uint32 *num_buf_alloc)
BufferAccessStrategy GetAccessStrategy(BufferAccessStrategyType btype)
BufferDesc * StrategyGetBuffer(BufferAccessStrategy strategy, uint32 *buf_state, bool *from_ring)
void FreeAccessStrategy(BufferAccessStrategy strategy)
IOContext IOContextForStrategy(BufferAccessStrategy strategy)
void StrategyFreeBuffer(BufferDesc *buf)
bool StrategyRejectBuffer(BufferAccessStrategy strategy, BufferDesc *buf, bool from_ring)
volatile sig_atomic_t ProcSignalBarrierPending
BufferUsage pgBufferUsage
void on_shmem_exit(pg_on_exit_callback function, Datum arg)
if(TABLE==NULL||TABLE_index==NULL)
static volatile sig_atomic_t waiting
void LockRelationForExtension(Relation relation, LOCKMODE lockmode)
void UnlockRelationForExtension(Relation relation, LOCKMODE lockmode)
void UnpinLocalBuffer(Buffer buffer)
BufferDesc * LocalBufferAlloc(SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum, bool *foundPtr)
void AtEOXact_LocalBuffers(bool isCommit)
void DropRelationLocalBuffers(RelFileLocator rlocator, ForkNumber forkNum, BlockNumber firstDelBlock)
void AtProcExit_LocalBuffers(void)
bool PinLocalBuffer(BufferDesc *buf_hdr, bool adjust_usagecount)
void MarkLocalBufferDirty(Buffer buffer)
void DropRelationAllLocalBuffers(RelFileLocator rlocator)
PrefetchBufferResult PrefetchLocalBuffer(SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum)
BlockNumber ExtendBufferedRelLocal(BufferManagerRelation bmr, ForkNumber fork, uint32 flags, uint32 extend_by, BlockNumber extend_upto, Buffer *buffers, uint32 *extended_by)
void UnpinLocalBufferNoOwner(Buffer buffer)
bool LWLockHeldByMe(LWLock *lock)
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
bool LWLockHeldByMeInMode(LWLock *lock, LWLockMode mode)
void LWLockRelease(LWLock *lock)
bool LWLockConditionalAcquire(LWLock *lock, LWLockMode mode)
void pfree(void *pointer)
void * repalloc(void *pointer, Size size)
#define VALGRIND_MAKE_MEM_DEFINED(addr, size)
#define VALGRIND_MAKE_MEM_NOACCESS(addr, size)
#define START_CRIT_SECTION()
#define CHECK_FOR_INTERRUPTS()
#define END_CRIT_SECTION()
#define ERRCODE_DATA_CORRUPTED
static PgChecksumMode mode
#define WRITEBACK_MAX_PENDING_FLUSHES
#define DEFAULT_BACKEND_FLUSH_AFTER
#define DEFAULT_CHECKPOINT_FLUSH_AFTER
#define DEFAULT_BGWRITER_FLUSH_AFTER
#define pgstat_count_buffer_read(rel)
#define pgstat_count_buffer_hit(rel)
PgStat_BgWriterStats PendingBgWriterStats
PgStat_CheckpointerStats PendingCheckpointerStats
instr_time pgstat_prepare_io_time(bool track_io_guc)
void pgstat_count_io_op_time(IOObject io_object, IOContext io_context, IOOp io_op, instr_time start_time, uint32 cnt)
void pgstat_count_io_op(IOObject io_object, IOContext io_context, IOOp io_op)
#define qsort(a, b, c, d)
static Datum PointerGetDatum(const void *X)
static Pointer DatumGetPointer(Datum X)
static int32 DatumGetInt32(Datum X)
#define NUM_AUXILIARY_PROCS
#define DELAY_CHKPT_START
#define INVALID_PROC_NUMBER
void ProcessProcSignalBarrier(void)
@ PROCSIG_RECOVERY_CONFLICT_BUFFERPIN
void set_ps_display_remove_suffix(void)
void set_ps_display_suffix(const char *suffix)
char * psprintf(const char *fmt,...)
static unsigned hash(unsigned *uv, int n)
static SMgrRelation RelationGetSmgr(Relation rel)
#define RelationUsesLocalBuffers(relation)
#define RELATION_IS_OTHER_TEMP(relation)
#define RelationIsValid(relation)
#define RelFileLocatorBackendIsTemp(rlocator)
#define RelFileLocatorEquals(locator1, locator2)
#define relpath(rlocator, forknum)
#define relpathbackend(rlocator, backend, forknum)
#define relpathperm(rlocator, forknum)
ResourceOwner CurrentResourceOwner
void ResourceOwnerEnlarge(ResourceOwner owner)
#define RELEASE_PRIO_BUFFER_IOS
@ RESOURCE_RELEASE_BEFORE_LOCKS
#define RELEASE_PRIO_BUFFER_PINS
void perform_spin_delay(SpinDelayStatus *status)
void finish_spin_delay(SpinDelayStatus *status)
#define init_local_spin_delay(status)
BlockNumber smgrnblocks(SMgrRelation reln, ForkNumber forknum)
void smgrwriteback(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, BlockNumber nblocks)
SMgrRelation smgropen(RelFileLocator rlocator, ProcNumber backend)
void smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
BlockNumber smgrnblocks_cached(SMgrRelation reln, ForkNumber forknum)
void smgrzeroextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, int nblocks, bool skipFsync)
void smgrextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, const void *buffer, bool skipFsync)
bool smgrexists(SMgrRelation reln, ForkNumber forknum)
void smgrreadv(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, void **buffers, BlockNumber nblocks)
bool smgrprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, int nblocks)
static void smgrwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, const void *buffer, bool skipFsync)
void ProcSendSignal(ProcNumber procNumber)
int GetStartupBufferPinWaitBufId(void)
void SetStartupBufferPinWaitBufId(int bufid)
void ProcWaitForSignal(uint32 wait_event_info)
void ResolveRecoveryConflictWithBufferPin(void)
bool log_recovery_conflict_waits
void LogRecoveryConflict(ProcSignalReason reason, TimestampTz wait_start, TimestampTz now, VirtualTransactionId *wait_list, bool still_waiting)
bool RelFileLocatorSkippingWAL(RelFileLocator rlocator)
SMgrRelation RelationCreateStorage(RelFileLocator rlocator, char relpersistence, bool register_delete)
void log_smgrcreate(const RelFileLocator *rlocator, ForkNumber forkNum)
int wait_backend_pgprocno
struct SMgrRelationData * smgr
int64 shared_blks_dirtied
int64 shared_blks_written
struct ErrorContextCallback * previous
void(* callback)(void *arg)
PgStat_Counter buf_written_clean
PgStat_Counter maxwritten_clean
PgStat_Counter buffers_written
BufferAccessStrategy strategy
struct SMgrRelationData * smgr
RelFileLocator rd_locator
BlockNumber smgr_cached_nblocks[MAX_FORKNUM+1]
RelFileLocatorBackend smgr_rlocator
PendingWriteback pending_writebacks[WRITEBACK_MAX_PENDING_FLUSHES]
static uint64 table_relation_size(Relation rel, ForkNumber forkNumber)
bool RecoveryInProgress(void)
bool XLogNeedsFlush(XLogRecPtr record)
CheckpointStatsData CheckpointStats
void XLogFlush(XLogRecPtr record)
#define CHECKPOINT_END_OF_RECOVERY
#define CHECKPOINT_FLUSH_ALL
#define CHECKPOINT_IS_SHUTDOWN
#define XLogHintBitIsNeeded()
#define XLogRecPtrIsInvalid(r)
#define InvalidXLogRecPtr
XLogRecPtr XLogSaveBufferForHint(Buffer buffer, bool buffer_std)
XLogRecPtr log_newpage_buffer(Buffer buffer, bool page_std)