PostgreSQL Source Code  git master
localbuf.c File Reference
#include "postgres.h"
#include "access/parallel.h"
#include "catalog/catalog.h"
#include "executor/instrument.h"
#include "pgstat.h"
#include "storage/buf_internals.h"
#include "storage/bufmgr.h"
#include "utils/guc_hooks.h"
#include "utils/memutils.h"
#include "utils/resowner_private.h"
Include dependency graph for localbuf.c:

Go to the source code of this file.

Data Structures

struct  LocalBufferLookupEnt
 

Macros

#define LocalBufHdrGetBlock(bufHdr)    LocalBufferBlockPointers[-((bufHdr)->buf_id + 2)]
 

Functions

static void InitLocalBuffers (void)
 
static Block GetLocalBufferStorage (void)
 
PrefetchBufferResult PrefetchLocalBuffer (SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum)
 
BufferDescLocalBufferAlloc (SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum, bool *foundPtr)
 
void MarkLocalBufferDirty (Buffer buffer)
 
void DropRelationLocalBuffers (RelFileLocator rlocator, ForkNumber forkNum, BlockNumber firstDelBlock)
 
void DropRelationAllLocalBuffers (RelFileLocator rlocator)
 
bool check_temp_buffers (int *newval, void **extra, GucSource source)
 
static void CheckForLocalBufferLeaks (void)
 
void AtEOXact_LocalBuffers (bool isCommit)
 
void AtProcExit_LocalBuffers (void)
 

Variables

int NLocBuffer = 0
 
BufferDescLocalBufferDescriptors = NULL
 
BlockLocalBufferBlockPointers = NULL
 
int32LocalRefCount = NULL
 
static int nextFreeLocalBuf = 0
 
static HTABLocalBufHash = NULL
 

Macro Definition Documentation

◆ LocalBufHdrGetBlock

#define LocalBufHdrGetBlock (   bufHdr)     LocalBufferBlockPointers[-((bufHdr)->buf_id + 2)]

Definition at line 39 of file localbuf.c.

Function Documentation

◆ AtEOXact_LocalBuffers()

void AtEOXact_LocalBuffers ( bool  isCommit)

Definition at line 599 of file localbuf.c.

600 {
602 }
static void CheckForLocalBufferLeaks(void)
Definition: localbuf.c:570

References CheckForLocalBufferLeaks().

Referenced by AtEOXact_Buffers().

◆ AtProcExit_LocalBuffers()

void AtProcExit_LocalBuffers ( void  )

Definition at line 610 of file localbuf.c.

611 {
612  /*
613  * We shouldn't be holding any remaining pins; if we are, and assertions
614  * aren't enabled, we'll fail later in DropRelationBuffers while trying to
615  * drop the temp rels.
616  */
618 }

References CheckForLocalBufferLeaks().

Referenced by AtProcExit_Buffers().

◆ check_temp_buffers()

bool check_temp_buffers ( int *  newval,
void **  extra,
GucSource  source 
)

Definition at line 491 of file localbuf.c.

492 {
493  /*
494  * Once local buffers have been initialized, it's too late to change this.
495  * However, if this is only a test call, allow it.
496  */
497  if (source != PGC_S_TEST && NLocBuffer && NLocBuffer != *newval)
498  {
499  GUC_check_errdetail("\"temp_buffers\" cannot be changed after any temporary tables have been accessed in the session.");
500  return false;
501  }
502  return true;
503 }
#define newval
#define GUC_check_errdetail
Definition: guc.h:437
@ PGC_S_TEST
Definition: guc.h:121
int NLocBuffer
Definition: localbuf.c:42
static rewind_source * source
Definition: pg_rewind.c:87

References GUC_check_errdetail, newval, NLocBuffer, PGC_S_TEST, and source.

◆ CheckForLocalBufferLeaks()

static void CheckForLocalBufferLeaks ( void  )
static

Definition at line 570 of file localbuf.c.

571 {
572 #ifdef USE_ASSERT_CHECKING
573  if (LocalRefCount)
574  {
575  int RefCountErrors = 0;
576  int i;
577 
578  for (i = 0; i < NLocBuffer; i++)
579  {
580  if (LocalRefCount[i] != 0)
581  {
582  Buffer b = -i - 1;
583 
585  RefCountErrors++;
586  }
587  }
588  Assert(RefCountErrors == 0);
589  }
590 #endif
591 }
int Buffer
Definition: buf.h:23
void PrintBufferLeakWarning(Buffer buffer)
Definition: bufmgr.c:2733
int b
Definition: isn.c:70
int i
Definition: isn.c:73
Assert(fmt[strlen(fmt) - 1] !='\n')
int32 * LocalRefCount
Definition: localbuf.c:46

References Assert(), b, i, LocalRefCount, NLocBuffer, and PrintBufferLeakWarning().

Referenced by AtEOXact_LocalBuffers(), and AtProcExit_LocalBuffers().

◆ DropRelationAllLocalBuffers()

void DropRelationAllLocalBuffers ( RelFileLocator  rlocator)

Definition at line 377 of file localbuf.c.

378 {
379  int i;
380 
381  for (i = 0; i < NLocBuffer; i++)
382  {
384  LocalBufferLookupEnt *hresult;
385  uint32 buf_state;
386 
387  buf_state = pg_atomic_read_u32(&bufHdr->state);
388 
389  if ((buf_state & BM_TAG_VALID) &&
390  BufTagMatchesRelFileLocator(&bufHdr->tag, &rlocator))
391  {
392  if (LocalRefCount[i] != 0)
393  elog(ERROR, "block %u of %s is still referenced (local %u)",
394  bufHdr->tag.blockNum,
396  MyBackendId,
397  BufTagGetForkNum(&bufHdr->tag)),
398  LocalRefCount[i]);
399  /* Remove entry from hashtable */
400  hresult = (LocalBufferLookupEnt *)
401  hash_search(LocalBufHash, &bufHdr->tag, HASH_REMOVE, NULL);
402  if (!hresult) /* shouldn't happen */
403  elog(ERROR, "local buffer hash table corrupted");
404  /* Mark buffer invalid */
405  ClearBufferTag(&bufHdr->tag);
406  buf_state &= ~BUF_FLAG_MASK;
407  buf_state &= ~BUF_USAGECOUNT_MASK;
408  pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
409  }
410  }
411 }
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
#define BM_TAG_VALID
Definition: buf_internals.h:62
#define BUF_USAGECOUNT_MASK
Definition: buf_internals.h:44
static ForkNumber BufTagGetForkNum(const BufferTag *tag)
static BufferDesc * GetLocalBufferDescriptor(uint32 id)
static bool BufTagMatchesRelFileLocator(const BufferTag *tag, const RelFileLocator *rlocator)
#define BUF_FLAG_MASK
Definition: buf_internals.h:47
static void ClearBufferTag(BufferTag *tag)
static RelFileLocator BufTagGetRelFileLocator(const BufferTag *tag)
unsigned int uint32
Definition: c.h:490
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:953
#define ERROR
Definition: elog.h:39
BackendId MyBackendId
Definition: globals.c:85
@ HASH_REMOVE
Definition: hsearch.h:115
static HTAB * LocalBufHash
Definition: localbuf.c:50
#define relpathbackend(rlocator, backend, forknum)
Definition: relpath.h:85
BufferTag tag
pg_atomic_uint32 state
BlockNumber blockNum
Definition: buf_internals.h:97

References buftag::blockNum, BM_TAG_VALID, BUF_FLAG_MASK, BUF_USAGECOUNT_MASK, BufTagGetForkNum(), BufTagGetRelFileLocator(), BufTagMatchesRelFileLocator(), ClearBufferTag(), elog(), ERROR, GetLocalBufferDescriptor(), HASH_REMOVE, hash_search(), i, LocalBufHash, LocalRefCount, MyBackendId, NLocBuffer, pg_atomic_read_u32(), pg_atomic_unlocked_write_u32(), relpathbackend, BufferDesc::state, and BufferDesc::tag.

Referenced by DropRelationsAllBuffers().

◆ DropRelationLocalBuffers()

void DropRelationLocalBuffers ( RelFileLocator  rlocator,
ForkNumber  forkNum,
BlockNumber  firstDelBlock 
)

Definition at line 329 of file localbuf.c.

331 {
332  int i;
333 
334  for (i = 0; i < NLocBuffer; i++)
335  {
337  LocalBufferLookupEnt *hresult;
338  uint32 buf_state;
339 
340  buf_state = pg_atomic_read_u32(&bufHdr->state);
341 
342  if ((buf_state & BM_TAG_VALID) &&
343  BufTagMatchesRelFileLocator(&bufHdr->tag, &rlocator) &&
344  BufTagGetForkNum(&bufHdr->tag) == forkNum &&
345  bufHdr->tag.blockNum >= firstDelBlock)
346  {
347  if (LocalRefCount[i] != 0)
348  elog(ERROR, "block %u of %s is still referenced (local %u)",
349  bufHdr->tag.blockNum,
351  MyBackendId,
352  BufTagGetForkNum(&bufHdr->tag)),
353  LocalRefCount[i]);
354 
355  /* Remove entry from hashtable */
356  hresult = (LocalBufferLookupEnt *)
357  hash_search(LocalBufHash, &bufHdr->tag, HASH_REMOVE, NULL);
358  if (!hresult) /* shouldn't happen */
359  elog(ERROR, "local buffer hash table corrupted");
360  /* Mark buffer invalid */
361  ClearBufferTag(&bufHdr->tag);
362  buf_state &= ~BUF_FLAG_MASK;
363  buf_state &= ~BUF_USAGECOUNT_MASK;
364  pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
365  }
366  }
367 }

References buftag::blockNum, BM_TAG_VALID, BUF_FLAG_MASK, BUF_USAGECOUNT_MASK, BufTagGetForkNum(), BufTagGetRelFileLocator(), BufTagMatchesRelFileLocator(), ClearBufferTag(), elog(), ERROR, GetLocalBufferDescriptor(), HASH_REMOVE, hash_search(), i, LocalBufHash, LocalRefCount, MyBackendId, NLocBuffer, pg_atomic_read_u32(), pg_atomic_unlocked_write_u32(), relpathbackend, BufferDesc::state, and BufferDesc::tag.

Referenced by DropRelationBuffers().

◆ GetLocalBufferStorage()

static Block GetLocalBufferStorage ( void  )
static

Definition at line 515 of file localbuf.c.

516 {
517  static char *cur_block = NULL;
518  static int next_buf_in_block = 0;
519  static int num_bufs_in_block = 0;
520  static int total_bufs_allocated = 0;
521  static MemoryContext LocalBufferContext = NULL;
522 
523  char *this_buf;
524 
525  Assert(total_bufs_allocated < NLocBuffer);
526 
527  if (next_buf_in_block >= num_bufs_in_block)
528  {
529  /* Need to make a new request to memmgr */
530  int num_bufs;
531 
532  /*
533  * We allocate local buffers in a context of their own, so that the
534  * space eaten for them is easily recognizable in MemoryContextStats
535  * output. Create the context on first use.
536  */
537  if (LocalBufferContext == NULL)
538  LocalBufferContext =
540  "LocalBufferContext",
542 
543  /* Start with a 16-buffer request; subsequent ones double each time */
544  num_bufs = Max(num_bufs_in_block * 2, 16);
545  /* But not more than what we need for all remaining local bufs */
546  num_bufs = Min(num_bufs, NLocBuffer - total_bufs_allocated);
547  /* And don't overflow MaxAllocSize, either */
548  num_bufs = Min(num_bufs, MaxAllocSize / BLCKSZ);
549 
550  cur_block = (char *) MemoryContextAlloc(LocalBufferContext,
551  num_bufs * BLCKSZ);
552  next_buf_in_block = 0;
553  num_bufs_in_block = num_bufs;
554  }
555 
556  /* Allocate next buffer in current memory block */
557  this_buf = cur_block + next_buf_in_block * BLCKSZ;
558  next_buf_in_block++;
559  total_bufs_allocated++;
560 
561  return (Block) this_buf;
562 }
void * Block
Definition: bufmgr.h:24
#define Min(x, y)
Definition: c.h:988
#define Max(x, y)
Definition: c.h:982
MemoryContext TopMemoryContext
Definition: mcxt.c:141
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1005
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:153
#define MaxAllocSize
Definition: memutils.h:40

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Assert(), Max, MaxAllocSize, MemoryContextAlloc(), Min, NLocBuffer, and TopMemoryContext.

Referenced by LocalBufferAlloc().

◆ InitLocalBuffers()

static void InitLocalBuffers ( void  )
static

Definition at line 420 of file localbuf.c.

421 {
422  int nbufs = num_temp_buffers;
423  HASHCTL info;
424  int i;
425 
426  /*
427  * Parallel workers can't access data in temporary tables, because they
428  * have no visibility into the local buffers of their leader. This is a
429  * convenient, low-cost place to provide a backstop check for that. Note
430  * that we don't wish to prevent a parallel worker from accessing catalog
431  * metadata about a temp table, so checks at higher levels would be
432  * inappropriate.
433  */
434  if (IsParallelWorker())
435  ereport(ERROR,
436  (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
437  errmsg("cannot access temporary tables during a parallel operation")));
438 
439  /* Allocate and zero buffer headers and auxiliary arrays */
440  LocalBufferDescriptors = (BufferDesc *) calloc(nbufs, sizeof(BufferDesc));
441  LocalBufferBlockPointers = (Block *) calloc(nbufs, sizeof(Block));
442  LocalRefCount = (int32 *) calloc(nbufs, sizeof(int32));
444  ereport(FATAL,
445  (errcode(ERRCODE_OUT_OF_MEMORY),
446  errmsg("out of memory")));
447 
448  nextFreeLocalBuf = 0;
449 
450  /* initialize fields that need to start off nonzero */
451  for (i = 0; i < nbufs; i++)
452  {
454 
455  /*
456  * negative to indicate local buffer. This is tricky: shared buffers
457  * start with 0. We have to start with -2. (Note that the routine
458  * BufferDescriptorGetBuffer adds 1 to buf_id so our first buffer id
459  * is -1.)
460  */
461  buf->buf_id = -i - 2;
462 
463  /*
464  * Intentionally do not initialize the buffer's atomic variable
465  * (besides zeroing the underlying memory above). That way we get
466  * errors on platforms without atomics, if somebody (re-)introduces
467  * atomic operations for local buffers.
468  */
469  }
470 
471  /* Create the lookup hash table */
472  info.keysize = sizeof(BufferTag);
473  info.entrysize = sizeof(LocalBufferLookupEnt);
474 
475  LocalBufHash = hash_create("Local Buffer Lookup Table",
476  nbufs,
477  &info,
479 
480  if (!LocalBufHash)
481  elog(ERROR, "could not initialize local buffer hash table");
482 
483  /* Initialization done, mark buffers allocated */
484  NLocBuffer = nbufs;
485 }
struct buftag BufferTag
signed int int32
Definition: c.h:478
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:350
int errcode(int sqlerrcode)
Definition: elog.c:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define FATAL
Definition: elog.h:41
#define ereport(elevel,...)
Definition: elog.h:149
int num_temp_buffers
Definition: guc_tables.c:525
#define calloc(a, b)
Definition: header.h:55
#define HASH_ELEM
Definition: hsearch.h:95
#define HASH_BLOBS
Definition: hsearch.h:97
#define IsParallelWorker()
Definition: parallel.h:61
Block * LocalBufferBlockPointers
Definition: localbuf.c:45
BufferDesc * LocalBufferDescriptors
Definition: localbuf.c:44
static int nextFreeLocalBuf
Definition: localbuf.c:48
static char * buf
Definition: pg_test_fsync.c:67
Size keysize
Definition: hsearch.h:75
Size entrysize
Definition: hsearch.h:76

References buf, calloc, elog(), HASHCTL::entrysize, ereport, errcode(), errmsg(), ERROR, FATAL, GetLocalBufferDescriptor(), HASH_BLOBS, hash_create(), HASH_ELEM, i, IsParallelWorker, HASHCTL::keysize, LocalBufferBlockPointers, LocalBufferDescriptors, LocalBufHash, LocalRefCount, nextFreeLocalBuf, NLocBuffer, and num_temp_buffers.

Referenced by LocalBufferAlloc(), and PrefetchLocalBuffer().

◆ LocalBufferAlloc()

BufferDesc* LocalBufferAlloc ( SMgrRelation  smgr,
ForkNumber  forkNum,
BlockNumber  blockNum,
bool foundPtr 
)

Definition at line 110 of file localbuf.c.

112 {
113  BufferTag newTag; /* identity of requested block */
114  LocalBufferLookupEnt *hresult;
115  BufferDesc *bufHdr;
116  int b;
117  int trycounter;
118  bool found;
119  uint32 buf_state;
120 
121  InitBufferTag(&newTag, &smgr->smgr_rlocator.locator, forkNum, blockNum);
122 
123  /* Initialize local buffers if first request in this session */
124  if (LocalBufHash == NULL)
126 
127  /* See if the desired buffer already exists */
128  hresult = (LocalBufferLookupEnt *)
129  hash_search(LocalBufHash, &newTag, HASH_FIND, NULL);
130 
131  if (hresult)
132  {
133  b = hresult->id;
134  bufHdr = GetLocalBufferDescriptor(b);
135  Assert(BufferTagsEqual(&bufHdr->tag, &newTag));
136 #ifdef LBDEBUG
137  fprintf(stderr, "LB ALLOC (%u,%d,%d) %d\n",
138  smgr->smgr_rlocator.locator.relNumber, forkNum, blockNum, -b - 1);
139 #endif
140  buf_state = pg_atomic_read_u32(&bufHdr->state);
141 
142  /* this part is equivalent to PinBuffer for a shared buffer */
143  if (LocalRefCount[b] == 0)
144  {
146  {
147  buf_state += BUF_USAGECOUNT_ONE;
148  pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
149  }
150  }
151  LocalRefCount[b]++;
153  BufferDescriptorGetBuffer(bufHdr));
154  if (buf_state & BM_VALID)
155  *foundPtr = true;
156  else
157  {
158  /* Previous read attempt must have failed; try again */
159  *foundPtr = false;
160  }
161  return bufHdr;
162  }
163 
164 #ifdef LBDEBUG
165  fprintf(stderr, "LB ALLOC (%u,%d,%d) %d\n",
166  smgr->smgr_rlocator.locator.relNumber, forkNum, blockNum,
167  -nextFreeLocalBuf - 1);
168 #endif
169 
170  /*
171  * Need to get a new buffer. We use a clock sweep algorithm (essentially
172  * the same as what freelist.c does now...)
173  */
174  trycounter = NLocBuffer;
175  for (;;)
176  {
178 
179  if (++nextFreeLocalBuf >= NLocBuffer)
180  nextFreeLocalBuf = 0;
181 
182  bufHdr = GetLocalBufferDescriptor(b);
183 
184  if (LocalRefCount[b] == 0)
185  {
186  buf_state = pg_atomic_read_u32(&bufHdr->state);
187 
188  if (BUF_STATE_GET_USAGECOUNT(buf_state) > 0)
189  {
190  buf_state -= BUF_USAGECOUNT_ONE;
191  pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
192  trycounter = NLocBuffer;
193  }
194  else
195  {
196  /* Found a usable buffer */
197  LocalRefCount[b]++;
199  BufferDescriptorGetBuffer(bufHdr));
200  break;
201  }
202  }
203  else if (--trycounter == 0)
204  ereport(ERROR,
205  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
206  errmsg("no empty local buffer available")));
207  }
208 
209  /*
210  * this buffer is not referenced but it might still be dirty. if that's
211  * the case, write it out before reusing it!
212  */
213  if (buf_state & BM_DIRTY)
214  {
215  SMgrRelation oreln;
216  Page localpage = (char *) LocalBufHdrGetBlock(bufHdr);
217 
218  /* Find smgr relation for buffer */
219  oreln = smgropen(BufTagGetRelFileLocator(&bufHdr->tag), MyBackendId);
220 
221  PageSetChecksumInplace(localpage, bufHdr->tag.blockNum);
222 
223  /* And write... */
224  smgrwrite(oreln,
225  BufTagGetForkNum(&bufHdr->tag),
226  bufHdr->tag.blockNum,
227  localpage,
228  false);
229 
230  /* Mark not-dirty now in case we error out below */
231  buf_state &= ~BM_DIRTY;
232  pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
233 
234  /* Temporary table I/O does not use Buffer Access Strategies */
237  }
238 
239  /*
240  * lazy memory allocation: allocate space on first use of a buffer.
241  */
242  if (LocalBufHdrGetBlock(bufHdr) == NULL)
243  {
244  /* Set pointer for use by BufferGetBlock() macro */
246  }
247 
248  /*
249  * Update the hash table: remove old entry, if any, and make new one.
250  */
251  if (buf_state & BM_TAG_VALID)
252  {
253  hresult = (LocalBufferLookupEnt *)
254  hash_search(LocalBufHash, &bufHdr->tag, HASH_REMOVE, NULL);
255  if (!hresult) /* shouldn't happen */
256  elog(ERROR, "local buffer hash table corrupted");
257  /* mark buffer invalid just in case hash insert fails */
258  ClearBufferTag(&bufHdr->tag);
259  buf_state &= ~(BM_VALID | BM_TAG_VALID);
260  pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
262  }
263 
264  hresult = (LocalBufferLookupEnt *)
265  hash_search(LocalBufHash, &newTag, HASH_ENTER, &found);
266  if (found) /* shouldn't happen */
267  elog(ERROR, "local buffer hash table corrupted");
268  hresult->id = b;
269 
270  /*
271  * it's all ours now.
272  */
273  bufHdr->tag = newTag;
274  buf_state &= ~(BM_VALID | BM_DIRTY | BM_JUST_DIRTIED | BM_IO_ERROR);
275  buf_state |= BM_TAG_VALID;
276  buf_state &= ~BUF_USAGECOUNT_MASK;
277  buf_state += BUF_USAGECOUNT_ONE;
278  pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
279 
280  *foundPtr = false;
281  return bufHdr;
282 }
#define BM_MAX_USAGE_COUNT
Definition: buf_internals.h:77
static void InitBufferTag(BufferTag *tag, const RelFileLocator *rlocator, ForkNumber forkNum, BlockNumber blockNum)
static bool BufferTagsEqual(const BufferTag *tag1, const BufferTag *tag2)
#define BM_DIRTY
Definition: buf_internals.h:60
#define BM_JUST_DIRTIED
Definition: buf_internals.h:65
#define BUF_STATE_GET_USAGECOUNT(state)
Definition: buf_internals.h:51
#define BUF_USAGECOUNT_ONE
Definition: buf_internals.h:45
#define BM_VALID
Definition: buf_internals.h:61
#define BM_IO_ERROR
Definition: buf_internals.h:64
static Buffer BufferDescriptorGetBuffer(const BufferDesc *bdesc)
void PageSetChecksumInplace(Page page, BlockNumber blkno)
Definition: bufpage.c:1539
Pointer Page
Definition: bufpage.h:78
@ HASH_FIND
Definition: hsearch.h:113
@ HASH_ENTER
Definition: hsearch.h:114
BufferUsage pgBufferUsage
Definition: instrument.c:20
#define LocalBufHdrGetBlock(bufHdr)
Definition: localbuf.c:39
static Block GetLocalBufferStorage(void)
Definition: localbuf.c:515
static void InitLocalBuffers(void)
Definition: localbuf.c:420
@ IOOBJECT_TEMP_RELATION
Definition: pgstat.h:279
@ IOCONTEXT_NORMAL
Definition: pgstat.h:288
@ IOOP_EVICT
Definition: pgstat.h:296
@ IOOP_WRITE
Definition: pgstat.h:302
void pgstat_count_io_op(IOObject io_object, IOContext io_context, IOOp io_op)
Definition: pgstat_io.c:66
#define fprintf
Definition: port.h:242
ResourceOwner CurrentResourceOwner
Definition: resowner.c:146
void ResourceOwnerRememberBuffer(ResourceOwner owner, Buffer buffer)
Definition: resowner.c:963
void smgrwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, const void *buffer, bool skipFsync)
Definition: smgr.c:554
SMgrRelation smgropen(RelFileLocator rlocator, BackendId backend)
Definition: smgr.c:146
int64 local_blks_written
Definition: instrument.h:33
RelFileLocator locator
RelFileNumber relNumber
RelFileLocatorBackend smgr_rlocator
Definition: smgr.h:42

References Assert(), b, buftag::blockNum, BM_DIRTY, BM_IO_ERROR, BM_JUST_DIRTIED, BM_MAX_USAGE_COUNT, BM_TAG_VALID, BM_VALID, BUF_STATE_GET_USAGECOUNT, BUF_USAGECOUNT_MASK, BUF_USAGECOUNT_ONE, BufferDescriptorGetBuffer(), BufferTagsEqual(), BufTagGetForkNum(), BufTagGetRelFileLocator(), ClearBufferTag(), CurrentResourceOwner, elog(), ereport, errcode(), errmsg(), ERROR, fprintf, GetLocalBufferDescriptor(), GetLocalBufferStorage(), HASH_ENTER, HASH_FIND, HASH_REMOVE, hash_search(), LocalBufferLookupEnt::id, InitBufferTag(), InitLocalBuffers(), IOCONTEXT_NORMAL, IOOBJECT_TEMP_RELATION, IOOP_EVICT, IOOP_WRITE, BufferUsage::local_blks_written, LocalBufHash, LocalBufHdrGetBlock, LocalRefCount, RelFileLocatorBackend::locator, MyBackendId, nextFreeLocalBuf, NLocBuffer, PageSetChecksumInplace(), pg_atomic_read_u32(), pg_atomic_unlocked_write_u32(), pgBufferUsage, pgstat_count_io_op(), RelFileLocator::relNumber, ResourceOwnerRememberBuffer(), SMgrRelationData::smgr_rlocator, smgropen(), smgrwrite(), BufferDesc::state, and BufferDesc::tag.

Referenced by ReadBuffer_common().

◆ MarkLocalBufferDirty()

void MarkLocalBufferDirty ( Buffer  buffer)

Definition at line 289 of file localbuf.c.

290 {
291  int bufid;
292  BufferDesc *bufHdr;
293  uint32 buf_state;
294 
295  Assert(BufferIsLocal(buffer));
296 
297 #ifdef LBDEBUG
298  fprintf(stderr, "LB DIRTY %d\n", buffer);
299 #endif
300 
301  bufid = -buffer - 1;
302 
303  Assert(LocalRefCount[bufid] > 0);
304 
305  bufHdr = GetLocalBufferDescriptor(bufid);
306 
307  buf_state = pg_atomic_read_u32(&bufHdr->state);
308 
309  if (!(buf_state & BM_DIRTY))
311 
312  buf_state |= BM_DIRTY;
313 
314  pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
315 }
#define BufferIsLocal(buffer)
Definition: buf.h:37
int64 local_blks_dirtied
Definition: instrument.h:32

References Assert(), BM_DIRTY, BufferIsLocal, fprintf, GetLocalBufferDescriptor(), BufferUsage::local_blks_dirtied, LocalRefCount, pg_atomic_read_u32(), pg_atomic_unlocked_write_u32(), pgBufferUsage, and BufferDesc::state.

Referenced by MarkBufferDirty(), and MarkBufferDirtyHint().

◆ PrefetchLocalBuffer()

PrefetchBufferResult PrefetchLocalBuffer ( SMgrRelation  smgr,
ForkNumber  forkNum,
BlockNumber  blockNum 
)

Definition at line 65 of file localbuf.c.

67 {
68  PrefetchBufferResult result = {InvalidBuffer, false};
69  BufferTag newTag; /* identity of requested block */
70  LocalBufferLookupEnt *hresult;
71 
72  InitBufferTag(&newTag, &smgr->smgr_rlocator.locator, forkNum, blockNum);
73 
74  /* Initialize local buffers if first request in this session */
75  if (LocalBufHash == NULL)
77 
78  /* See if the desired buffer already exists */
79  hresult = (LocalBufferLookupEnt *)
80  hash_search(LocalBufHash, &newTag, HASH_FIND, NULL);
81 
82  if (hresult)
83  {
84  /* Yes, so nothing to do */
85  result.recent_buffer = -hresult->id - 1;
86  }
87  else
88  {
89 #ifdef USE_PREFETCH
90  /* Not in buffers, so initiate prefetch */
91  smgrprefetch(smgr, forkNum, blockNum);
92  result.initiated_io = true;
93 #endif /* USE_PREFETCH */
94  }
95 
96  return result;
97 }
#define InvalidBuffer
Definition: buf.h:25
bool smgrprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum)
Definition: smgr.c:518
Buffer recent_buffer
Definition: bufmgr.h:59

References HASH_FIND, hash_search(), LocalBufferLookupEnt::id, InitBufferTag(), PrefetchBufferResult::initiated_io, InitLocalBuffers(), InvalidBuffer, LocalBufHash, RelFileLocatorBackend::locator, PrefetchBufferResult::recent_buffer, SMgrRelationData::smgr_rlocator, and smgrprefetch().

Referenced by PrefetchBuffer().

Variable Documentation

◆ LocalBufferBlockPointers

Block* LocalBufferBlockPointers = NULL

Definition at line 45 of file localbuf.c.

Referenced by BufferGetBlock(), and InitLocalBuffers().

◆ LocalBufferDescriptors

BufferDesc* LocalBufferDescriptors = NULL

Definition at line 44 of file localbuf.c.

Referenced by GetLocalBufferDescriptor(), and InitLocalBuffers().

◆ LocalBufHash

HTAB* LocalBufHash = NULL
static

◆ LocalRefCount

◆ nextFreeLocalBuf

int nextFreeLocalBuf = 0
static

Definition at line 48 of file localbuf.c.

Referenced by InitLocalBuffers(), and LocalBufferAlloc().

◆ NLocBuffer