PostgreSQL Source Code git master
Loading...
Searching...
No Matches
localbuf.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * localbuf.c
4 * local buffer manager. Fast buffer manager for temporary tables,
5 * which never need to be WAL-logged or checkpointed, etc.
6 *
7 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994-5, Regents of the University of California
9 *
10 *
11 * IDENTIFICATION
12 * src/backend/storage/buffer/localbuf.c
13 *
14 *-------------------------------------------------------------------------
15 */
16#include "postgres.h"
17
18#include "access/parallel.h"
19#include "executor/instrument.h"
20#include "pgstat.h"
21#include "storage/aio.h"
23#include "storage/bufmgr.h"
24#include "storage/fd.h"
25#include "utils/guc_hooks.h"
26#include "utils/memdebug.h"
27#include "utils/memutils.h"
28#include "utils/rel.h"
29#include "utils/resowner.h"
30
31
32/*#define LBDEBUG*/
33
34/* entry for buffer lookup hashtable */
35typedef struct
36{
37 BufferTag key; /* Tag of a disk page */
38 int id; /* Associated local buffer's index */
40
41/* Note: this macro only works on local buffers, not shared ones! */
42#define LocalBufHdrGetBlock(bufHdr) \
43 LocalBufferBlockPointers[-((bufHdr)->buf_id + 2)]
44
45int NLocBuffer = 0; /* until buffers are initialized */
46
50
51static int nextFreeLocalBufId = 0;
52
54
55/* number of local buffers pinned at least once */
56static int NLocalPinnedBuffers = 0;
57
58
59static void InitLocalBuffers(void);
60static Block GetLocalBufferStorage(void);
61static Buffer GetLocalVictimBuffer(void);
62
63
64/*
65 * PrefetchLocalBuffer -
66 * initiate asynchronous read of a block of a relation
67 *
68 * Do PrefetchBuffer's work for temporary relations.
69 * No-op if prefetching isn't compiled in.
70 */
73 BlockNumber blockNum)
74{
76 BufferTag newTag; /* identity of requested block */
78
79 InitBufferTag(&newTag, &smgr->smgr_rlocator.locator, forkNum, blockNum);
80
81 /* Initialize local buffers if first request in this session */
82 if (LocalBufHash == NULL)
84
85 /* See if the desired buffer already exists */
88
89 if (hresult)
90 {
91 /* Yes, so nothing to do */
92 result.recent_buffer = -hresult->id - 1;
93 }
94 else
95 {
96#ifdef USE_PREFETCH
97 /* Not in buffers, so initiate prefetch */
98 if ((io_direct_flags & IO_DIRECT_DATA) == 0 &&
99 smgrprefetch(smgr, forkNum, blockNum, 1))
100 {
101 result.initiated_io = true;
102 }
103#endif /* USE_PREFETCH */
104 }
105
106 return result;
107}
108
109
110/*
111 * LocalBufferAlloc -
112 * Find or create a local buffer for the given page of the given relation.
113 *
114 * API is similar to bufmgr.c's BufferAlloc, except that we do not need to do
115 * any locking since this is all local. We support only default access
116 * strategy (hence, usage_count is always advanced).
117 */
120 bool *foundPtr)
121{
122 BufferTag newTag; /* identity of requested block */
126 int bufid;
127 bool found;
128
129 InitBufferTag(&newTag, &smgr->smgr_rlocator.locator, forkNum, blockNum);
130
131 /* Initialize local buffers if first request in this session */
132 if (LocalBufHash == NULL)
134
136
137 /* See if the desired buffer already exists */
140
141 if (hresult)
142 {
143 bufid = hresult->id;
146
148 }
149 else
150 {
152
154 bufid = -victim_buffer - 1;
156
159 if (found) /* shouldn't happen */
160 elog(ERROR, "local buffer hash table corrupted");
161 hresult->id = bufid;
162
163 /*
164 * it's all ours now.
165 */
166 bufHdr->tag = newTag;
167
172
173 *foundPtr = false;
174 }
175
176 return bufHdr;
177}
178
179/*
180 * Like FlushBuffer(), just for local buffers.
181 */
182void
184{
187
189
190 /*
191 * Try to start an I/O operation. There currently are no reasons for
192 * StartLocalBufferIO to return anything other than
193 * BUFFER_IO_READY_FOR_IO, so we raise an error in that case.
194 */
196 elog(ERROR, "failed to start write IO on local buffer");
197
198 /* Find smgr relation for buffer */
199 if (reln == NULL)
202
203 PageSetChecksum(localpage, bufHdr->tag.blockNum);
204
206
207 /* And write... */
210 bufHdr->tag.blockNum,
211 localpage,
212 false);
213
214 /* Temporary table I/O does not use Buffer Access Strategies */
217
218 /* Mark not-dirty */
219 TerminateLocalBufferIO(bufHdr, true, 0, false);
220
222}
223
224static Buffer
226{
227 int victim_bufid;
228 int trycounter;
230
232
233 /*
234 * Need to get a new buffer. We use a clock-sweep algorithm (essentially
235 * the same as what freelist.c does now...)
236 */
238 for (;;)
239 {
241
244
246
247 if (LocalRefCount[victim_bufid] == 0)
248 {
250
252 {
256 }
257 else if (BUF_STATE_GET_REFCOUNT(buf_state) > 0)
258 {
259 /*
260 * This can be reached if the backend initiated AIO for this
261 * buffer and then errored out.
262 */
263 }
264 else
265 {
266 /* Found a usable buffer */
267 PinLocalBuffer(bufHdr, false);
268 break;
269 }
270 }
271 else if (--trycounter == 0)
274 errmsg("no empty local buffer available")));
275 }
276
277 /*
278 * lazy memory allocation: allocate space on first use of a buffer.
279 */
281 {
282 /* Set pointer for use by BufferGetBlock() macro */
284 }
285
286 /*
287 * this buffer is not referenced but it might still be dirty. if that's
288 * the case, write it out before reusing it!
289 */
290 if (pg_atomic_read_u64(&bufHdr->state) & BM_DIRTY)
292
293 /*
294 * Remove the victim buffer from the hashtable and mark as invalid.
295 */
297 {
299
301 }
302
304}
305
306/* see GetPinLimit() */
307uint32
309{
310 /* Every backend has its own temporary buffers, and can pin them all. */
311 return num_temp_buffers;
312}
313
314/* see GetAdditionalPinLimit() */
315uint32
321
322/* see LimitAdditionalPins() */
323void
325{
327
328 if (*additional_pins <= 1)
329 return;
330
331 /*
332 * In contrast to LimitAdditionalPins() other backends don't play a role
333 * here. We can allow up to NLocBuffer pins in total, but it might not be
334 * initialized yet so read num_temp_buffers.
335 */
337
340}
341
342/*
343 * Implementation of ExtendBufferedRelBy() and ExtendBufferedRelTo() for
344 * temporary buffers.
345 */
349 uint32 flags,
352 Buffer *buffers,
354{
357
358 /* Initialize local buffers if first request in this session */
359 if (LocalBufHash == NULL)
361
363
364 for (uint32 i = 0; i < extend_by; i++)
365 {
368
369 buffers[i] = GetLocalVictimBuffer();
370 buf_hdr = GetLocalBufferDescriptor(-buffers[i] - 1);
372
373 /* new buffers are zero-filled */
375 }
376
378
380 {
381 /*
382 * In contrast to shared relations, nothing could change the relation
383 * size concurrently. Thus we shouldn't end up finding that we don't
384 * need to do anything.
385 */
387
389 }
390
391 /* Fail if relation is already at maximum possible length */
395 errmsg("cannot extend relation %s beyond %u blocks",
396 relpath(BMR_GET_SMGR(bmr)->smgr_rlocator, fork).str,
398
399 for (uint32 i = 0; i < extend_by; i++)
400 {
401 int victim_buf_id;
403 BufferTag tag;
405 bool found;
406
407 victim_buf_id = -buffers[i] - 1;
409
410 /* in case we need to pin an existing buffer below */
412
413 InitBufferTag(&tag, &BMR_GET_SMGR(bmr)->smgr_rlocator.locator, fork,
414 first_block + i);
415
417 hash_search(LocalBufHash, &tag, HASH_ENTER, &found);
418 if (found)
419 {
422
424
428
429 /*
430 * Clear the BM_VALID bit, do StartLocalBufferIO() and proceed.
431 */
437
438 /* no need to loop for local buffers */
440 }
441 else
442 {
444
446
447 victim_buf_hdr->tag = tag;
448
450
452
454
456 }
457 }
458
460
461 /* actually extend relation */
463
466
467 for (uint32 i = 0; i < extend_by; i++)
468 {
469 Buffer buf = buffers[i];
472
474
478 }
479
481
483
484 return first_block;
485}
486
487/*
488 * MarkLocalBufferDirty -
489 * mark a local buffer dirty
490 */
491void
493{
494 int bufid;
497
498 Assert(BufferIsLocal(buffer));
499
500#ifdef LBDEBUG
501 fprintf(stderr, "LB DIRTY %d\n", buffer);
502#endif
503
504 bufid = -buffer - 1;
505
507
509
511
512 if (!(buf_state & BM_DIRTY))
514
516
518}
519
520/*
521 * Like StartSharedBufferIO, but for local buffers
522 */
525{
527
528 /*
529 * With AIO the buffer could have IO in progress, e.g. when there are two
530 * scans of the same relation. Either wait for the other IO (if wait =
531 * true and io_wref == NULL) or return BUFFER_IO_IN_PROGRESS;
532 */
533 if (pgaio_wref_valid(&bufHdr->io_wref))
534 {
535 PgAioWaitRef buf_wref = bufHdr->io_wref;
536
537 if (io_wref != NULL)
538 {
539 /* We've already asynchronously started this IO, so join it */
540 *io_wref = buf_wref;
542 }
543
544 /*
545 * For temp buffers we should never need to wait in
546 * StartLocalBufferIO() when called with io_wref == NULL while there
547 * are staged IOs, as it's not allowed to call code that is not aware
548 * of AIO while in batch mode.
549 */
551
552 if (!wait)
554
556 }
557
558 /* Once we get here, there is definitely no I/O active on this buffer */
559
560 /* Check if someone else already did the I/O */
563 {
565 }
566
567 /* BM_IO_IN_PROGRESS isn't currently used for local buffers */
568
569 /* local buffers don't track IO using resowners */
570
572}
573
574/*
575 * Like TerminateBufferIO, but for local buffers
576 */
577void
579 bool release_aio)
580{
581 /* Only need to adjust flags */
583
584 /* BM_IO_IN_PROGRESS isn't currently used for local buffers */
585
586 /* Clear earlier errors, if this IO failed, it'll be marked again */
588
589 if (clear_dirty)
591
592 if (release_aio)
593 {
594 /* release pin held by IO subsystem, see also buffer_stage_common() */
597 pgaio_wref_clear(&bufHdr->io_wref);
598 }
599
602
603 /* local buffers don't track IO using resowners */
604
605 /* local buffers don't use the IO CV, as no other process can see buffer */
606
607 /* local buffers don't use BM_PIN_COUNT_WAITER, so no need to wake */
608}
609
610/*
611 * InvalidateLocalBuffer -- mark a local buffer invalid.
612 *
613 * If check_unreferenced is true, error out if the buffer is still
614 * pinned. Passing false is appropriate when calling InvalidateLocalBuffer()
615 * as part of changing the identity of a buffer, instead of just dropping the
616 * buffer.
617 *
618 * See also InvalidateBuffer().
619 */
620void
622{
624 int bufid = -buffer - 1;
627
628 /*
629 * It's possible that we started IO on this buffer before e.g. aborting
630 * the transaction that created a table. We need to wait for that IO to
631 * complete before removing / reusing the buffer.
632 */
633 if (pgaio_wref_valid(&bufHdr->io_wref))
634 {
635 PgAioWaitRef iow = bufHdr->io_wref;
636
638 Assert(!pgaio_wref_valid(&bufHdr->io_wref));
639 }
640
642
643 /*
644 * We need to test not just LocalRefCount[bufid] but also the BufferDesc
645 * itself, as the latter is used to represent a pin by the AIO subsystem.
646 * This can happen if AIO is initiated and then the query errors out.
647 */
648 if (check_unreferenced &&
650 elog(ERROR, "block %u of %s is still referenced (local %d)",
651 bufHdr->tag.blockNum,
654 BufTagGetForkNum(&bufHdr->tag)).str,
656
657 /* Remove entry from hashtable */
660 if (!hresult) /* shouldn't happen */
661 elog(ERROR, "local buffer hash table corrupted");
662 /* Mark buffer invalid */
663 ClearBufferTag(&bufHdr->tag);
667}
668
669/*
670 * DropRelationLocalBuffers
671 * This function removes from the buffer pool all the pages of the
672 * specified relation that have block numbers >= firstDelBlock.
673 * (In particular, with firstDelBlock = 0, all pages are removed.)
674 * Dirty pages are simply dropped, without bothering to write them
675 * out first. Therefore, this is NOT rollback-able, and so should be
676 * used only with extreme caution!
677 *
678 * See DropRelationBuffers in bufmgr.c for more notes.
679 */
680void
683{
684 int i;
685 int j;
686
687 for (i = 0; i < NLocBuffer; i++)
688 {
691
693
694 if (!(buf_state & BM_TAG_VALID) ||
695 !BufTagMatchesRelFileLocator(&bufHdr->tag, &rlocator))
696 continue;
697
698 for (j = 0; j < nforks; j++)
699 {
700 if (BufTagGetForkNum(&bufHdr->tag) == forkNum[j] &&
701 bufHdr->tag.blockNum >= firstDelBlock[j])
702 {
704 break;
705 }
706 }
707 }
708}
709
710/*
711 * DropRelationAllLocalBuffers
712 * This function removes from the buffer pool all pages of all forks
713 * of the specified relation.
714 *
715 * See DropRelationsAllBuffers in bufmgr.c for more notes.
716 */
717void
719{
720 int i;
721
722 for (i = 0; i < NLocBuffer; i++)
723 {
726
728
729 if ((buf_state & BM_TAG_VALID) &&
730 BufTagMatchesRelFileLocator(&bufHdr->tag, &rlocator))
731 {
733 }
734 }
735}
736
737/*
738 * InitLocalBuffers -
739 * init the local buffer cache. Since most queries (esp. multi-user ones)
740 * don't involve local buffers, we delay allocating actual memory for the
741 * buffers until we need them; just make the buffer headers here.
742 */
743static void
745{
747 HASHCTL info;
748 int i;
749
750 /*
751 * Parallel workers can't access data in temporary tables, because they
752 * have no visibility into the local buffers of their leader. This is a
753 * convenient, low-cost place to provide a backstop check for that. Note
754 * that we don't wish to prevent a parallel worker from accessing catalog
755 * metadata about a temp table, so checks at higher levels would be
756 * inappropriate.
757 */
758 if (IsParallelWorker())
761 errmsg("cannot access temporary tables during a parallel operation")));
762
763 /* Allocate and zero buffer headers and auxiliary arrays */
766 LocalRefCount = (int32 *) calloc(nbufs, sizeof(int32));
770 errmsg("out of memory")));
771
773
774 /* initialize fields that need to start off nonzero */
775 for (i = 0; i < nbufs; i++)
776 {
778
779 /*
780 * negative to indicate local buffer. This is tricky: shared buffers
781 * start with 0. We have to start with -2. (Note that the routine
782 * BufferDescriptorGetBuffer adds 1 to buf_id so our first buffer id
783 * is -1.)
784 */
785 buf->buf_id = -i - 2;
786
787 pgaio_wref_clear(&buf->io_wref);
788
789 /*
790 * Intentionally do not initialize the buffer's atomic variable
791 * (besides zeroing the underlying memory above). That way we get
792 * errors on platforms without atomics, if somebody (re-)introduces
793 * atomic operations for local buffers.
794 */
795 }
796
797 /* Create the lookup hash table */
798 info.keysize = sizeof(BufferTag);
799 info.entrysize = sizeof(LocalBufferLookupEnt);
800
801 LocalBufHash = hash_create("Local Buffer Lookup Table",
802 nbufs,
803 &info,
805
806 if (!LocalBufHash)
807 elog(ERROR, "could not initialize local buffer hash table");
808
809 /* Initialization done, mark buffers allocated */
811}
812
813/*
814 * XXX: We could have a slightly more efficient version of PinLocalBuffer()
815 * that does not support adjusting the usagecount - but so far it does not
816 * seem worth the trouble.
817 *
818 * Note that ResourceOwnerEnlarge() must have been done already.
819 */
820bool
822{
825 int bufid = -buffer - 1;
826
828
829 if (LocalRefCount[bufid] == 0)
830 {
833 if (adjust_usagecount &&
835 {
837 }
839
840 /*
841 * See comment in PinBuffer().
842 *
843 * If the buffer isn't allocated yet, it'll be marked as defined in
844 * GetLocalBufferStorage().
845 */
848 }
852
853 return buf_state & BM_VALID;
854}
855
856void
862
863void
865{
866 int buffid = -buffer - 1;
867
868 Assert(BufferIsLocal(buffer));
871
872 if (--LocalRefCount[buffid] == 0)
873 {
876
878
883
884 /* see comment in UnpinBufferNoOwner */
886 }
887}
888
889/*
890 * GUC check_hook for temp_buffers
891 */
892bool
894{
895 /*
896 * Once local buffers have been initialized, it's too late to change this.
897 * However, if this is only a test call, allow it.
898 */
900 {
901 GUC_check_errdetail("\"temp_buffers\" cannot be changed after any temporary tables have been accessed in the session.");
902 return false;
903 }
904 return true;
905}
906
907/*
908 * GetLocalBufferStorage - allocate memory for a local buffer
909 *
910 * The idea of this function is to aggregate our requests for storage
911 * so that the memory manager doesn't see a whole lot of relatively small
912 * requests. Since we'll never give back a local buffer once it's created
913 * within a particular process, no point in burdening memmgr with separately
914 * managed chunks.
915 */
916static Block
918{
919 static char *cur_block = NULL;
920 static int next_buf_in_block = 0;
921 static int num_bufs_in_block = 0;
922 static int total_bufs_allocated = 0;
924
925 char *this_buf;
926
928
930 {
931 /* Need to make a new request to memmgr */
932 int num_bufs;
933
934 /*
935 * We allocate local buffers in a context of their own, so that the
936 * space eaten for them is easily recognizable in MemoryContextStats
937 * output. Create the context on first use.
938 */
942 "LocalBufferContext",
944
945 /* Start with a 16-buffer request; subsequent ones double each time */
946 num_bufs = Max(num_bufs_in_block * 2, 16);
947 /* But not more than what we need for all remaining local bufs */
949 /* And don't overflow MaxAllocSize, either */
951
952 /* Buffers should be I/O aligned. */
956 0);
957
960 }
961
962 /* Allocate next buffer in current memory block */
966
967 /*
968 * Caller's PinLocalBuffer() was too early for Valgrind updates, so do it
969 * here. The block is actually undefined, but we want consistency with
970 * the regular case of not needing to allocate memory. This is
971 * specifically needed when method_io_uring.c fills the block, because
972 * Valgrind doesn't recognize io_uring reads causing undefined memory to
973 * become defined.
974 */
976
977 return (Block) this_buf;
978}
979
980/*
981 * CheckForLocalBufferLeaks - ensure this backend holds no local buffer pins
982 *
983 * This is just like CheckForBufferLeaks(), but for local buffers.
984 */
985static void
987{
988#ifdef USE_ASSERT_CHECKING
989 if (LocalRefCount)
990 {
991 int RefCountErrors = 0;
992 int i;
993
994 for (i = 0; i < NLocBuffer; i++)
995 {
996 if (LocalRefCount[i] != 0)
997 {
998 Buffer b = -i - 1;
999 char *s;
1000
1002 elog(WARNING, "local buffer refcount leak: %s", s);
1003 pfree(s);
1004
1006 }
1007 }
1008 Assert(RefCountErrors == 0);
1009 }
1010#endif
1011}
1012
1013/*
1014 * AtEOXact_LocalBuffers - clean up at end of transaction.
1015 *
1016 * This is just like AtEOXact_Buffers, but for local buffers.
1017 */
1018void
1023
1024/*
1025 * AtProcExit_LocalBuffers - ensure we have dropped pins during backend exit.
1026 *
1027 * This is just like AtProcExit_Buffers, but for local buffers.
1028 */
1029void
1031{
1032 /*
1033 * We shouldn't be holding any remaining pins; if we are, and assertions
1034 * aren't enabled, we'll fail later in DropRelationBuffers while trying to
1035 * drop the temp rels.
1036 */
1038}
bool pgaio_wref_valid(PgAioWaitRef *iow)
Definition aio.c:971
void pgaio_wref_clear(PgAioWaitRef *iow)
Definition aio.c:964
bool pgaio_have_staged(void)
Definition aio.c:1117
void pgaio_wref_wait(PgAioWaitRef *iow)
Definition aio.c:991
static void pg_atomic_unlocked_write_u64(volatile pg_atomic_uint64 *ptr, uint64 val)
Definition atomics.h:494
static uint64 pg_atomic_read_u64(volatile pg_atomic_uint64 *ptr)
Definition atomics.h:467
uint32 BlockNumber
Definition block.h:31
#define InvalidBlockNumber
Definition block.h:33
#define MaxBlockNumber
Definition block.h:35
int Buffer
Definition buf.h:23
#define InvalidBuffer
Definition buf.h:25
#define BufferIsLocal(buffer)
Definition buf.h:37
#define BM_MAX_USAGE_COUNT
static void InitBufferTag(BufferTag *tag, const RelFileLocator *rlocator, ForkNumber forkNum, BlockNumber blockNum)
#define BM_TAG_VALID
#define BUF_USAGECOUNT_MASK
static ForkNumber BufTagGetForkNum(const BufferTag *tag)
#define BUF_REFCOUNT_ONE
static bool BufferTagsEqual(const BufferTag *tag1, const BufferTag *tag2)
static bool BufTagMatchesRelFileLocator(const BufferTag *tag, const RelFileLocator *rlocator)
#define BUF_FLAG_MASK
#define BM_DIRTY
#define BUF_STATE_GET_USAGECOUNT(state)
StartBufferIOResult
@ BUFFER_IO_IN_PROGRESS
@ BUFFER_IO_ALREADY_DONE
@ BUFFER_IO_READY_FOR_IO
static void ClearBufferTag(BufferTag *tag)
static void ResourceOwnerRememberBuffer(ResourceOwner owner, Buffer buffer)
struct buftag BufferTag
static void ResourceOwnerForgetBuffer(ResourceOwner owner, Buffer buffer)
#define BUF_USAGECOUNT_ONE
#define BUF_STATE_GET_REFCOUNT(state)
static RelFileLocator BufTagGetRelFileLocator(const BufferTag *tag)
#define BM_VALID
static BufferDesc * GetLocalBufferDescriptor(uint32 id)
static Buffer BufferDescriptorGetBuffer(const BufferDesc *bdesc)
bool track_io_timing
Definition bufmgr.c:192
char * DebugPrintBufferRefcount(Buffer buffer)
Definition bufmgr.c:4389
void * Block
Definition bufmgr.h:26
#define BMR_GET_SMGR(bmr)
Definition bufmgr.h:118
void PageSetChecksum(Page page, BlockNumber blkno)
Definition bufpage.c:1518
PageData * Page
Definition bufpage.h:81
#define Min(x, y)
Definition c.h:1091
#define Max(x, y)
Definition c.h:1085
#define Assert(condition)
Definition c.h:943
int32_t int32
Definition c.h:620
uint64_t uint64
Definition c.h:625
uint32_t uint32
Definition c.h:624
#define MemSet(start, val, len)
Definition c.h:1107
uint32 result
#define fprintf(file, fmt, msg)
Definition cubescan.l:21
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition dynahash.c:889
HTAB * hash_create(const char *tabname, int64 nelem, const HASHCTL *info, int flags)
Definition dynahash.c:360
int errcode(int sqlerrcode)
Definition elog.c:874
#define FATAL
Definition elog.h:42
#define WARNING
Definition elog.h:37
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
#define ereport(elevel,...)
Definition elog.h:152
int io_direct_flags
Definition fd.c:172
#define IO_DIRECT_DATA
Definition fd.h:54
#define MaxAllocSize
Definition fe_memutils.h:22
ProcNumber MyProcNumber
Definition globals.c:92
#define newval
#define GUC_check_errdetail
Definition guc.h:507
GucSource
Definition guc.h:112
@ PGC_S_TEST
Definition guc.h:125
int num_temp_buffers
Definition guc_tables.c:580
const char * str
@ HASH_FIND
Definition hsearch.h:108
@ HASH_REMOVE
Definition hsearch.h:110
@ HASH_ENTER
Definition hsearch.h:109
#define HASH_ELEM
Definition hsearch.h:90
#define HASH_BLOBS
Definition hsearch.h:92
#define IsParallelWorker()
Definition parallel.h:62
BufferUsage pgBufferUsage
Definition instrument.c:25
int b
Definition isn.c:74
int j
Definition isn.c:78
int i
Definition isn.c:77
int32 * LocalRefCount
Definition localbuf.c:49
void FlushLocalBuffer(BufferDesc *bufHdr, SMgrRelation reln)
Definition localbuf.c:183
void UnpinLocalBuffer(Buffer buffer)
Definition localbuf.c:857
static HTAB * LocalBufHash
Definition localbuf.c:53
static int NLocalPinnedBuffers
Definition localbuf.c:56
void AtEOXact_LocalBuffers(bool isCommit)
Definition localbuf.c:1019
#define LocalBufHdrGetBlock(bufHdr)
Definition localbuf.c:42
static void CheckForLocalBufferLeaks(void)
Definition localbuf.c:986
uint32 GetAdditionalLocalPinLimit(void)
Definition localbuf.c:316
StartBufferIOResult StartLocalBufferIO(BufferDesc *bufHdr, bool forInput, bool wait, PgAioWaitRef *io_wref)
Definition localbuf.c:524
static Block GetLocalBufferStorage(void)
Definition localbuf.c:917
static int nextFreeLocalBufId
Definition localbuf.c:51
bool check_temp_buffers(int *newval, void **extra, GucSource source)
Definition localbuf.c:893
void AtProcExit_LocalBuffers(void)
Definition localbuf.c:1030
bool PinLocalBuffer(BufferDesc *buf_hdr, bool adjust_usagecount)
Definition localbuf.c:821
static void InitLocalBuffers(void)
Definition localbuf.c:744
void LimitAdditionalLocalPins(uint32 *additional_pins)
Definition localbuf.c:324
uint32 GetLocalPinLimit(void)
Definition localbuf.c:308
static Buffer GetLocalVictimBuffer(void)
Definition localbuf.c:225
void MarkLocalBufferDirty(Buffer buffer)
Definition localbuf.c:492
void DropRelationAllLocalBuffers(RelFileLocator rlocator)
Definition localbuf.c:718
void InvalidateLocalBuffer(BufferDesc *bufHdr, bool check_unreferenced)
Definition localbuf.c:621
void TerminateLocalBufferIO(BufferDesc *bufHdr, bool clear_dirty, uint64 set_flag_bits, bool release_aio)
Definition localbuf.c:578
int NLocBuffer
Definition localbuf.c:45
PrefetchBufferResult PrefetchLocalBuffer(SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum)
Definition localbuf.c:72
BlockNumber ExtendBufferedRelLocal(BufferManagerRelation bmr, ForkNumber fork, uint32 flags, uint32 extend_by, BlockNumber extend_upto, Buffer *buffers, uint32 *extended_by)
Definition localbuf.c:347
Block * LocalBufferBlockPointers
Definition localbuf.c:48
void UnpinLocalBufferNoOwner(Buffer buffer)
Definition localbuf.c:864
void DropRelationLocalBuffers(RelFileLocator rlocator, ForkNumber *forkNum, int nforks, BlockNumber *firstDelBlock)
Definition localbuf.c:681
BufferDesc * LocalBufferDescriptors
Definition localbuf.c:47
BufferDesc * LocalBufferAlloc(SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum, bool *foundPtr)
Definition localbuf.c:119
void pfree(void *pointer)
Definition mcxt.c:1616
void * MemoryContextAllocAligned(MemoryContext context, Size size, Size alignto, int flags)
Definition mcxt.c:1482
MemoryContext TopMemoryContext
Definition mcxt.c:166
#define VALGRIND_MAKE_MEM_DEFINED(addr, size)
Definition memdebug.h:26
#define VALGRIND_MAKE_MEM_NOACCESS(addr, size)
Definition memdebug.h:27
#define AllocSetContextCreate
Definition memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition memutils.h:160
static char * errmsg
#define PG_IO_ALIGN_SIZE
static rewind_source * source
Definition pg_rewind.c:89
static char buf[DEFAULT_XLOG_SEG_SIZE]
@ IOOBJECT_TEMP_RELATION
Definition pgstat.h:282
@ IOCONTEXT_NORMAL
Definition pgstat.h:293
@ IOOP_EXTEND
Definition pgstat.h:318
@ IOOP_EVICT
Definition pgstat.h:311
@ IOOP_WRITE
Definition pgstat.h:320
instr_time pgstat_prepare_io_time(bool track_io_guc)
Definition pgstat_io.c:91
void pgstat_count_io_op(IOObject io_object, IOContext io_context, IOOp io_op, uint32 cnt, uint64 bytes)
Definition pgstat_io.c:68
void pgstat_count_io_op_time(IOObject io_object, IOContext io_context, IOOp io_op, instr_time start_time, uint32 cnt, uint64 bytes)
Definition pgstat_io.c:122
static int fb(int x)
ForkNumber
Definition relpath.h:56
#define relpath(rlocator, forknum)
Definition relpath.h:150
#define relpathbackend(rlocator, backend, forknum)
Definition relpath.h:141
ResourceOwner CurrentResourceOwner
Definition resowner.c:173
void ResourceOwnerEnlarge(ResourceOwner owner)
Definition resowner.c:449
BlockNumber smgrnblocks(SMgrRelation reln, ForkNumber forknum)
Definition smgr.c:819
SMgrRelation smgropen(RelFileLocator rlocator, ProcNumber backend)
Definition smgr.c:240
void smgrzeroextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, int nblocks, bool skipFsync)
Definition smgr.c:649
bool smgrprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, int nblocks)
Definition smgr.c:678
static void smgrwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, const void *buffer, bool skipFsync)
Definition smgr.h:131
#define calloc(a, b)
int64 local_blks_written
Definition instrument.h:33
int64 local_blks_dirtied
Definition instrument.h:32
Size keysize
Definition hsearch.h:69
Size entrysize
Definition hsearch.h:70
RelFileLocator locator
RelFileLocatorBackend smgr_rlocator
Definition smgr.h:38