PostgreSQL Source Code  git master
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-2022, 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 "catalog/catalog.h"
20 #include "executor/instrument.h"
21 #include "storage/buf_internals.h"
22 #include "storage/bufmgr.h"
23 #include "utils/guc_hooks.h"
24 #include "utils/memutils.h"
25 #include "utils/resowner_private.h"
26 
27 
28 /*#define LBDEBUG*/
29 
30 /* entry for buffer lookup hashtable */
31 typedef struct
32 {
33  BufferTag key; /* Tag of a disk page */
34  int id; /* Associated local buffer's index */
36 
37 /* Note: this macro only works on local buffers, not shared ones! */
38 #define LocalBufHdrGetBlock(bufHdr) \
39  LocalBufferBlockPointers[-((bufHdr)->buf_id + 2)]
40 
41 int NLocBuffer = 0; /* until buffers are initialized */
42 
46 
47 static int nextFreeLocalBuf = 0;
48 
49 static HTAB *LocalBufHash = NULL;
50 
51 
52 static void InitLocalBuffers(void);
53 static Block GetLocalBufferStorage(void);
54 
55 
56 /*
57  * PrefetchLocalBuffer -
58  * initiate asynchronous read of a block of a relation
59  *
60  * Do PrefetchBuffer's work for temporary relations.
61  * No-op if prefetching isn't compiled in.
62  */
65  BlockNumber blockNum)
66 {
67  PrefetchBufferResult result = {InvalidBuffer, false};
68  BufferTag newTag; /* identity of requested block */
69  LocalBufferLookupEnt *hresult;
70 
71  InitBufferTag(&newTag, &smgr->smgr_rlocator.locator, forkNum, blockNum);
72 
73  /* Initialize local buffers if first request in this session */
74  if (LocalBufHash == NULL)
76 
77  /* See if the desired buffer already exists */
78  hresult = (LocalBufferLookupEnt *)
79  hash_search(LocalBufHash, (void *) &newTag, HASH_FIND, NULL);
80 
81  if (hresult)
82  {
83  /* Yes, so nothing to do */
84  result.recent_buffer = -hresult->id - 1;
85  }
86  else
87  {
88 #ifdef USE_PREFETCH
89  /* Not in buffers, so initiate prefetch */
90  smgrprefetch(smgr, forkNum, blockNum);
91  result.initiated_io = true;
92 #endif /* USE_PREFETCH */
93  }
94 
95  return result;
96 }
97 
98 
99 /*
100  * LocalBufferAlloc -
101  * Find or create a local buffer for the given page of the given relation.
102  *
103  * API is similar to bufmgr.c's BufferAlloc, except that we do not need
104  * to do any locking since this is all local. Also, IO_IN_PROGRESS
105  * does not get set. Lastly, we support only default access strategy
106  * (hence, usage_count is always advanced).
107  */
108 BufferDesc *
110  bool *foundPtr)
111 {
112  BufferTag newTag; /* identity of requested block */
113  LocalBufferLookupEnt *hresult;
114  BufferDesc *bufHdr;
115  int b;
116  int trycounter;
117  bool found;
118  uint32 buf_state;
119 
120  InitBufferTag(&newTag, &smgr->smgr_rlocator.locator, forkNum, blockNum);
121 
122  /* Initialize local buffers if first request in this session */
123  if (LocalBufHash == NULL)
125 
126  /* See if the desired buffer already exists */
127  hresult = (LocalBufferLookupEnt *)
128  hash_search(LocalBufHash, (void *) &newTag, HASH_FIND, NULL);
129 
130  if (hresult)
131  {
132  b = hresult->id;
133  bufHdr = GetLocalBufferDescriptor(b);
134  Assert(BufferTagsEqual(&bufHdr->tag, &newTag));
135 #ifdef LBDEBUG
136  fprintf(stderr, "LB ALLOC (%u,%d,%d) %d\n",
137  smgr->smgr_rlocator.locator.relNumber, forkNum, blockNum, -b - 1);
138 #endif
139  buf_state = pg_atomic_read_u32(&bufHdr->state);
140 
141  /* this part is equivalent to PinBuffer for a shared buffer */
142  if (LocalRefCount[b] == 0)
143  {
145  {
146  buf_state += BUF_USAGECOUNT_ONE;
147  pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
148  }
149  }
150  LocalRefCount[b]++;
152  BufferDescriptorGetBuffer(bufHdr));
153  if (buf_state & BM_VALID)
154  *foundPtr = true;
155  else
156  {
157  /* Previous read attempt must have failed; try again */
158  *foundPtr = false;
159  }
160  return bufHdr;
161  }
162 
163 #ifdef LBDEBUG
164  fprintf(stderr, "LB ALLOC (%u,%d,%d) %d\n",
165  smgr->smgr_rlocator.locator.relNumber, forkNum, blockNum,
166  -nextFreeLocalBuf - 1);
167 #endif
168 
169  /*
170  * Need to get a new buffer. We use a clock sweep algorithm (essentially
171  * the same as what freelist.c does now...)
172  */
173  trycounter = NLocBuffer;
174  for (;;)
175  {
177 
178  if (++nextFreeLocalBuf >= NLocBuffer)
179  nextFreeLocalBuf = 0;
180 
181  bufHdr = GetLocalBufferDescriptor(b);
182 
183  if (LocalRefCount[b] == 0)
184  {
185  buf_state = pg_atomic_read_u32(&bufHdr->state);
186 
187  if (BUF_STATE_GET_USAGECOUNT(buf_state) > 0)
188  {
189  buf_state -= BUF_USAGECOUNT_ONE;
190  pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
191  trycounter = NLocBuffer;
192  }
193  else
194  {
195  /* Found a usable buffer */
196  LocalRefCount[b]++;
198  BufferDescriptorGetBuffer(bufHdr));
199  break;
200  }
201  }
202  else if (--trycounter == 0)
203  ereport(ERROR,
204  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
205  errmsg("no empty local buffer available")));
206  }
207 
208  /*
209  * this buffer is not referenced but it might still be dirty. if that's
210  * the case, write it out before reusing it!
211  */
212  if (buf_state & BM_DIRTY)
213  {
214  SMgrRelation oreln;
215  Page localpage = (char *) LocalBufHdrGetBlock(bufHdr);
216 
217  /* Find smgr relation for buffer */
218  oreln = smgropen(BufTagGetRelFileLocator(&bufHdr->tag), MyBackendId);
219 
220  PageSetChecksumInplace(localpage, bufHdr->tag.blockNum);
221 
222  /* And write... */
223  smgrwrite(oreln,
224  BufTagGetForkNum(&bufHdr->tag),
225  bufHdr->tag.blockNum,
226  localpage,
227  false);
228 
229  /* Mark not-dirty now in case we error out below */
230  buf_state &= ~BM_DIRTY;
231  pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
232 
234  }
235 
236  /*
237  * lazy memory allocation: allocate space on first use of a buffer.
238  */
239  if (LocalBufHdrGetBlock(bufHdr) == NULL)
240  {
241  /* Set pointer for use by BufferGetBlock() macro */
243  }
244 
245  /*
246  * Update the hash table: remove old entry, if any, and make new one.
247  */
248  if (buf_state & BM_TAG_VALID)
249  {
250  hresult = (LocalBufferLookupEnt *)
251  hash_search(LocalBufHash, (void *) &bufHdr->tag,
252  HASH_REMOVE, NULL);
253  if (!hresult) /* shouldn't happen */
254  elog(ERROR, "local buffer hash table corrupted");
255  /* mark buffer invalid just in case hash insert fails */
256  ClearBufferTag(&bufHdr->tag);
257  buf_state &= ~(BM_VALID | BM_TAG_VALID);
258  pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
259  }
260 
261  hresult = (LocalBufferLookupEnt *)
262  hash_search(LocalBufHash, (void *) &newTag, HASH_ENTER, &found);
263  if (found) /* shouldn't happen */
264  elog(ERROR, "local buffer hash table corrupted");
265  hresult->id = b;
266 
267  /*
268  * it's all ours now.
269  */
270  bufHdr->tag = newTag;
271  buf_state &= ~(BM_VALID | BM_DIRTY | BM_JUST_DIRTIED | BM_IO_ERROR);
272  buf_state |= BM_TAG_VALID;
273  buf_state &= ~BUF_USAGECOUNT_MASK;
274  buf_state += BUF_USAGECOUNT_ONE;
275  pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
276 
277  *foundPtr = false;
278  return bufHdr;
279 }
280 
281 /*
282  * MarkLocalBufferDirty -
283  * mark a local buffer dirty
284  */
285 void
287 {
288  int bufid;
289  BufferDesc *bufHdr;
290  uint32 buf_state;
291 
292  Assert(BufferIsLocal(buffer));
293 
294 #ifdef LBDEBUG
295  fprintf(stderr, "LB DIRTY %d\n", buffer);
296 #endif
297 
298  bufid = -(buffer + 1);
299 
300  Assert(LocalRefCount[bufid] > 0);
301 
302  bufHdr = GetLocalBufferDescriptor(bufid);
303 
304  buf_state = pg_atomic_read_u32(&bufHdr->state);
305 
306  if (!(buf_state & BM_DIRTY))
308 
309  buf_state |= BM_DIRTY;
310 
311  pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
312 }
313 
314 /*
315  * DropRelationLocalBuffers
316  * This function removes from the buffer pool all the pages of the
317  * specified relation that have block numbers >= firstDelBlock.
318  * (In particular, with firstDelBlock = 0, all pages are removed.)
319  * Dirty pages are simply dropped, without bothering to write them
320  * out first. Therefore, this is NOT rollback-able, and so should be
321  * used only with extreme caution!
322  *
323  * See DropRelationBuffers in bufmgr.c for more notes.
324  */
325 void
327  BlockNumber firstDelBlock)
328 {
329  int i;
330 
331  for (i = 0; i < NLocBuffer; i++)
332  {
334  LocalBufferLookupEnt *hresult;
335  uint32 buf_state;
336 
337  buf_state = pg_atomic_read_u32(&bufHdr->state);
338 
339  if ((buf_state & BM_TAG_VALID) &&
340  BufTagMatchesRelFileLocator(&bufHdr->tag, &rlocator) &&
341  BufTagGetForkNum(&bufHdr->tag) == forkNum &&
342  bufHdr->tag.blockNum >= firstDelBlock)
343  {
344  if (LocalRefCount[i] != 0)
345  elog(ERROR, "block %u of %s is still referenced (local %u)",
346  bufHdr->tag.blockNum,
348  MyBackendId,
349  BufTagGetForkNum(&bufHdr->tag)),
350  LocalRefCount[i]);
351 
352  /* Remove entry from hashtable */
353  hresult = (LocalBufferLookupEnt *)
354  hash_search(LocalBufHash, (void *) &bufHdr->tag,
355  HASH_REMOVE, NULL);
356  if (!hresult) /* shouldn't happen */
357  elog(ERROR, "local buffer hash table corrupted");
358  /* Mark buffer invalid */
359  ClearBufferTag(&bufHdr->tag);
360  buf_state &= ~BUF_FLAG_MASK;
361  buf_state &= ~BUF_USAGECOUNT_MASK;
362  pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
363  }
364  }
365 }
366 
367 /*
368  * DropRelationAllLocalBuffers
369  * This function removes from the buffer pool all pages of all forks
370  * of the specified relation.
371  *
372  * See DropRelationsAllBuffers in bufmgr.c for more notes.
373  */
374 void
376 {
377  int i;
378 
379  for (i = 0; i < NLocBuffer; i++)
380  {
382  LocalBufferLookupEnt *hresult;
383  uint32 buf_state;
384 
385  buf_state = pg_atomic_read_u32(&bufHdr->state);
386 
387  if ((buf_state & BM_TAG_VALID) &&
388  BufTagMatchesRelFileLocator(&bufHdr->tag, &rlocator))
389  {
390  if (LocalRefCount[i] != 0)
391  elog(ERROR, "block %u of %s is still referenced (local %u)",
392  bufHdr->tag.blockNum,
394  MyBackendId,
395  BufTagGetForkNum(&bufHdr->tag)),
396  LocalRefCount[i]);
397  /* Remove entry from hashtable */
398  hresult = (LocalBufferLookupEnt *)
399  hash_search(LocalBufHash, (void *) &bufHdr->tag,
400  HASH_REMOVE, NULL);
401  if (!hresult) /* shouldn't happen */
402  elog(ERROR, "local buffer hash table corrupted");
403  /* Mark buffer invalid */
404  ClearBufferTag(&bufHdr->tag);
405  buf_state &= ~BUF_FLAG_MASK;
406  buf_state &= ~BUF_USAGECOUNT_MASK;
407  pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
408  }
409  }
410 }
411 
412 /*
413  * InitLocalBuffers -
414  * init the local buffer cache. Since most queries (esp. multi-user ones)
415  * don't involve local buffers, we delay allocating actual memory for the
416  * buffers until we need them; just make the buffer headers here.
417  */
418 static void
420 {
421  int nbufs = num_temp_buffers;
422  HASHCTL info;
423  int i;
424 
425  /*
426  * Parallel workers can't access data in temporary tables, because they
427  * have no visibility into the local buffers of their leader. This is a
428  * convenient, low-cost place to provide a backstop check for that. Note
429  * that we don't wish to prevent a parallel worker from accessing catalog
430  * metadata about a temp table, so checks at higher levels would be
431  * inappropriate.
432  */
433  if (IsParallelWorker())
434  ereport(ERROR,
435  (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
436  errmsg("cannot access temporary tables during a parallel operation")));
437 
438  /* Allocate and zero buffer headers and auxiliary arrays */
439  LocalBufferDescriptors = (BufferDesc *) calloc(nbufs, sizeof(BufferDesc));
440  LocalBufferBlockPointers = (Block *) calloc(nbufs, sizeof(Block));
441  LocalRefCount = (int32 *) calloc(nbufs, sizeof(int32));
443  ereport(FATAL,
444  (errcode(ERRCODE_OUT_OF_MEMORY),
445  errmsg("out of memory")));
446 
447  nextFreeLocalBuf = 0;
448 
449  /* initialize fields that need to start off nonzero */
450  for (i = 0; i < nbufs; i++)
451  {
453 
454  /*
455  * negative to indicate local buffer. This is tricky: shared buffers
456  * start with 0. We have to start with -2. (Note that the routine
457  * BufferDescriptorGetBuffer adds 1 to buf_id so our first buffer id
458  * is -1.)
459  */
460  buf->buf_id = -i - 2;
461 
462  /*
463  * Intentionally do not initialize the buffer's atomic variable
464  * (besides zeroing the underlying memory above). That way we get
465  * errors on platforms without atomics, if somebody (re-)introduces
466  * atomic operations for local buffers.
467  */
468  }
469 
470  /* Create the lookup hash table */
471  info.keysize = sizeof(BufferTag);
472  info.entrysize = sizeof(LocalBufferLookupEnt);
473 
474  LocalBufHash = hash_create("Local Buffer Lookup Table",
475  nbufs,
476  &info,
478 
479  if (!LocalBufHash)
480  elog(ERROR, "could not initialize local buffer hash table");
481 
482  /* Initialization done, mark buffers allocated */
483  NLocBuffer = nbufs;
484 }
485 
486 /*
487  * GUC check_hook for temp_buffers
488  */
489 bool
491 {
492  /*
493  * Once local buffers have been initialized, it's too late to change this.
494  * However, if this is only a test call, allow it.
495  */
496  if (source != PGC_S_TEST && NLocBuffer && NLocBuffer != *newval)
497  {
498  GUC_check_errdetail("\"temp_buffers\" cannot be changed after any temporary tables have been accessed in the session.");
499  return false;
500  }
501  return true;
502 }
503 
504 /*
505  * GetLocalBufferStorage - allocate memory for a local buffer
506  *
507  * The idea of this function is to aggregate our requests for storage
508  * so that the memory manager doesn't see a whole lot of relatively small
509  * requests. Since we'll never give back a local buffer once it's created
510  * within a particular process, no point in burdening memmgr with separately
511  * managed chunks.
512  */
513 static Block
515 {
516  static char *cur_block = NULL;
517  static int next_buf_in_block = 0;
518  static int num_bufs_in_block = 0;
519  static int total_bufs_allocated = 0;
520  static MemoryContext LocalBufferContext = NULL;
521 
522  char *this_buf;
523 
524  Assert(total_bufs_allocated < NLocBuffer);
525 
526  if (next_buf_in_block >= num_bufs_in_block)
527  {
528  /* Need to make a new request to memmgr */
529  int num_bufs;
530 
531  /*
532  * We allocate local buffers in a context of their own, so that the
533  * space eaten for them is easily recognizable in MemoryContextStats
534  * output. Create the context on first use.
535  */
536  if (LocalBufferContext == NULL)
537  LocalBufferContext =
539  "LocalBufferContext",
541 
542  /* Start with a 16-buffer request; subsequent ones double each time */
543  num_bufs = Max(num_bufs_in_block * 2, 16);
544  /* But not more than what we need for all remaining local bufs */
545  num_bufs = Min(num_bufs, NLocBuffer - total_bufs_allocated);
546  /* And don't overflow MaxAllocSize, either */
547  num_bufs = Min(num_bufs, MaxAllocSize / BLCKSZ);
548 
549  cur_block = (char *) MemoryContextAlloc(LocalBufferContext,
550  num_bufs * BLCKSZ);
551  next_buf_in_block = 0;
552  num_bufs_in_block = num_bufs;
553  }
554 
555  /* Allocate next buffer in current memory block */
556  this_buf = cur_block + next_buf_in_block * BLCKSZ;
557  next_buf_in_block++;
558  total_bufs_allocated++;
559 
560  return (Block) this_buf;
561 }
562 
563 /*
564  * CheckForLocalBufferLeaks - ensure this backend holds no local buffer pins
565  *
566  * This is just like CheckForBufferLeaks(), but for local buffers.
567  */
568 static void
570 {
571 #ifdef USE_ASSERT_CHECKING
572  if (LocalRefCount)
573  {
574  int RefCountErrors = 0;
575  int i;
576 
577  for (i = 0; i < NLocBuffer; i++)
578  {
579  if (LocalRefCount[i] != 0)
580  {
581  Buffer b = -i - 1;
582 
584  RefCountErrors++;
585  }
586  }
587  Assert(RefCountErrors == 0);
588  }
589 #endif
590 }
591 
592 /*
593  * AtEOXact_LocalBuffers - clean up at end of transaction.
594  *
595  * This is just like AtEOXact_Buffers, but for local buffers.
596  */
597 void
598 AtEOXact_LocalBuffers(bool isCommit)
599 {
601 }
602 
603 /*
604  * AtProcExit_LocalBuffers - ensure we have dropped pins during backend exit.
605  *
606  * This is just like AtProcExit_Buffers, but for local buffers.
607  */
608 void
610 {
611  /*
612  * We shouldn't be holding any remaining pins; if we are, and assertions
613  * aren't enabled, we'll fail later in DropRelationBuffers while
614  * trying to drop the temp rels.
615  */
617 }
static void pg_atomic_unlocked_write_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:272
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition: atomics.h:236
uint32 BlockNumber
Definition: block.h:31
int Buffer
Definition: buf.h:23
#define InvalidBuffer
Definition: buf.h:25
#define BufferIsLocal(buffer)
Definition: buf.h:37
#define BM_MAX_USAGE_COUNT
Definition: buf_internals.h:76
static void InitBufferTag(BufferTag *tag, const RelFileLocator *rlocator, ForkNumber forkNum, BlockNumber blockNum)
#define BM_TAG_VALID
Definition: buf_internals.h:61
#define BUF_USAGECOUNT_MASK
Definition: buf_internals.h:43
static ForkNumber BufTagGetForkNum(const BufferTag *tag)
static BufferDesc * GetLocalBufferDescriptor(uint32 id)
static bool BufferTagsEqual(const BufferTag *tag1, const BufferTag *tag2)
static bool BufTagMatchesRelFileLocator(const BufferTag *tag, const RelFileLocator *rlocator)
#define BUF_FLAG_MASK
Definition: buf_internals.h:46
#define BM_DIRTY
Definition: buf_internals.h:59
#define BM_JUST_DIRTIED
Definition: buf_internals.h:64
#define BUF_STATE_GET_USAGECOUNT(state)
Definition: buf_internals.h:50
static void ClearBufferTag(BufferTag *tag)
struct buftag BufferTag
#define BUF_USAGECOUNT_ONE
Definition: buf_internals.h:44
static RelFileLocator BufTagGetRelFileLocator(const BufferTag *tag)
#define BM_VALID
Definition: buf_internals.h:60
#define BM_IO_ERROR
Definition: buf_internals.h:63
static Buffer BufferDescriptorGetBuffer(const BufferDesc *bdesc)
void PrintBufferLeakWarning(Buffer buffer)
Definition: bufmgr.c:2695
void * Block
Definition: bufmgr.h:24
void PageSetChecksumInplace(Page page, BlockNumber blkno)
Definition: bufpage.c:1539
Pointer Page
Definition: bufpage.h:78
unsigned int uint32
Definition: c.h:442
#define Min(x, y)
Definition: c.h:937
signed int int32
Definition: c.h:430
#define Max(x, y)
Definition: c.h:931
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:953
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:350
int errcode(int sqlerrcode)
Definition: elog.c:695
int errmsg(const char *fmt,...)
Definition: elog.c:906
#define FATAL
Definition: elog.h:37
#define ERROR
Definition: elog.h:35
#define ereport(elevel,...)
Definition: elog.h:145
BackendId MyBackendId
Definition: globals.c:85
#define newval
#define GUC_check_errdetail
Definition: guc.h:434
GucSource
Definition: guc.h:108
@ PGC_S_TEST
Definition: guc.h:121
int num_temp_buffers
Definition: guc_tables.c:500
#define calloc(a, b)
Definition: header.h:55
@ HASH_FIND
Definition: hsearch.h:113
@ HASH_REMOVE
Definition: hsearch.h:115
@ HASH_ENTER
Definition: hsearch.h:114
#define HASH_ELEM
Definition: hsearch.h:95
#define HASH_BLOBS
Definition: hsearch.h:97
#define IsParallelWorker()
Definition: parallel.h:61
BufferUsage pgBufferUsage
Definition: instrument.c:20
int b
Definition: isn.c:70
int i
Definition: isn.c:73
Assert(fmt[strlen(fmt) - 1] !='\n')
int32 * LocalRefCount
Definition: localbuf.c:45
BufferDesc * LocalBufferAlloc(SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum, bool *foundPtr)
Definition: localbuf.c:109
static HTAB * LocalBufHash
Definition: localbuf.c:49
void AtEOXact_LocalBuffers(bool isCommit)
Definition: localbuf.c:598
#define LocalBufHdrGetBlock(bufHdr)
Definition: localbuf.c:38
static void CheckForLocalBufferLeaks(void)
Definition: localbuf.c:569
void DropRelationLocalBuffers(RelFileLocator rlocator, ForkNumber forkNum, BlockNumber firstDelBlock)
Definition: localbuf.c:326
static Block GetLocalBufferStorage(void)
Definition: localbuf.c:514
bool check_temp_buffers(int *newval, void **extra, GucSource source)
Definition: localbuf.c:490
void AtProcExit_LocalBuffers(void)
Definition: localbuf.c:609
static void InitLocalBuffers(void)
Definition: localbuf.c:419
void MarkLocalBufferDirty(Buffer buffer)
Definition: localbuf.c:286
void DropRelationAllLocalBuffers(RelFileLocator rlocator)
Definition: localbuf.c:375
int NLocBuffer
Definition: localbuf.c:41
PrefetchBufferResult PrefetchLocalBuffer(SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum)
Definition: localbuf.c:64
Block * LocalBufferBlockPointers
Definition: localbuf.c:44
BufferDesc * LocalBufferDescriptors
Definition: localbuf.c:43
static int nextFreeLocalBuf
Definition: localbuf.c:47
MemoryContext TopMemoryContext
Definition: mcxt.c:130
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:994
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:153
#define MaxAllocSize
Definition: memutils.h:40
static rewind_source * source
Definition: pg_rewind.c:81
static char * buf
Definition: pg_test_fsync.c:67
#define fprintf
Definition: port.h:242
ForkNumber
Definition: relpath.h:48
#define relpathbackend(rlocator, backend, forknum)
Definition: relpath.h:85
ResourceOwner CurrentResourceOwner
Definition: resowner.c:146
void ResourceOwnerRememberBuffer(ResourceOwner owner, Buffer buffer)
Definition: resowner.c:963
void smgrwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer, bool skipFsync)
Definition: smgr.c:554
bool smgrprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum)
Definition: smgr.c:518
SMgrRelation smgropen(RelFileLocator rlocator, BackendId backend)
Definition: smgr.c:146
BufferTag tag
pg_atomic_uint32 state
int64 local_blks_written
Definition: instrument.h:33
int64 local_blks_dirtied
Definition: instrument.h:32
Size keysize
Definition: hsearch.h:75
Size entrysize
Definition: hsearch.h:76
Definition: dynahash.c:220
Buffer recent_buffer
Definition: bufmgr.h:54
RelFileLocator locator
RelFileNumber relNumber
RelFileLocatorBackend smgr_rlocator
Definition: smgr.h:42
BlockNumber blockNum
Definition: buf_internals.h:96