PostgreSQL Source Code  git master
bufpage.c File Reference
#include "postgres.h"
#include "access/htup_details.h"
#include "access/itup.h"
#include "access/xlog.h"
#include "storage/checksum.h"
#include "utils/memdebug.h"
#include "utils/memutils.h"
Include dependency graph for bufpage.c:

Go to the source code of this file.

Data Structures

struct  itemIdSortData
 

Typedefs

typedef struct itemIdSortData itemIdSortData
 
typedef itemIdSortDataitemIdSort
 

Functions

void PageInit (Page page, Size pageSize, Size specialSize)
 
bool PageIsVerified (Page page, BlockNumber blkno)
 
OffsetNumber PageAddItemExtended (Page page, Item item, Size size, OffsetNumber offsetNumber, int flags)
 
Page PageGetTempPage (Page page)
 
Page PageGetTempPageCopy (Page page)
 
Page PageGetTempPageCopySpecial (Page page)
 
void PageRestoreTempPage (Page tempPage, Page oldPage)
 
static int itemoffcompare (const void *itemidp1, const void *itemidp2)
 
static void compactify_tuples (itemIdSort itemidbase, int nitems, Page page)
 
void PageRepairFragmentation (Page page)
 
Size PageGetFreeSpace (Page page)
 
Size PageGetFreeSpaceForMultipleTuples (Page page, int ntups)
 
Size PageGetExactFreeSpace (Page page)
 
Size PageGetHeapFreeSpace (Page page)
 
void PageIndexTupleDelete (Page page, OffsetNumber offnum)
 
void PageIndexMultiDelete (Page page, OffsetNumber *itemnos, int nitems)
 
void PageIndexTupleDeleteNoCompact (Page page, OffsetNumber offnum)
 
bool PageIndexTupleOverwrite (Page page, OffsetNumber offnum, Item newtup, Size newsize)
 
char * PageSetChecksumCopy (Page page, BlockNumber blkno)
 
void PageSetChecksumInplace (Page page, BlockNumber blkno)
 

Variables

bool ignore_checksum_failure = false
 

Typedef Documentation

◆ itemIdSort

Definition at line 426 of file bufpage.c.

◆ itemIdSortData

Function Documentation

◆ compactify_tuples()

static void compactify_tuples ( itemIdSort  itemidbase,
int  nitems,
Page  page 
)
static

Definition at line 441 of file bufpage.c.

References itemIdSortData::alignedlen, i, itemIdSortData::itemoff, itemoffcompare(), ItemIdData::lp_off, memmove, itemIdSortData::offsetindex, PageGetItemId, PageHeaderData::pd_special, PageHeaderData::pd_upper, qsort, and upper().

Referenced by PageIndexMultiDelete(), and PageRepairFragmentation().

442 {
443  PageHeader phdr = (PageHeader) page;
444  Offset upper;
445  int i;
446 
447  /* sort itemIdSortData array into decreasing itemoff order */
448  qsort((char *) itemidbase, nitems, sizeof(itemIdSortData),
450 
451  upper = phdr->pd_special;
452  for (i = 0; i < nitems; i++)
453  {
454  itemIdSort itemidptr = &itemidbase[i];
455  ItemId lp;
456 
457  lp = PageGetItemId(page, itemidptr->offsetindex + 1);
458  upper -= itemidptr->alignedlen;
459  memmove((char *) page + upper,
460  (char *) page + itemidptr->itemoff,
461  itemidptr->alignedlen);
462  lp->lp_off = upper;
463  }
464 
465  phdr->pd_upper = upper;
466 }
int16 itemoff
Definition: bufpage.c:423
Datum upper(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:74
uint16 alignedlen
Definition: bufpage.c:424
uint16 offsetindex
Definition: bufpage.c:422
#define memmove(d, s, c)
Definition: c.h:1045
LocationIndex pd_special
Definition: bufpage.h:156
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:231
unsigned lp_off
Definition: itemid.h:26
static int itemoffcompare(const void *itemidp1, const void *itemidp2)
Definition: bufpage.c:429
PageHeaderData * PageHeader
Definition: bufpage.h:162
signed int Offset
Definition: c.h:423
int i
#define qsort(a, b, c, d)
Definition: port.h:408
LocationIndex pd_upper
Definition: bufpage.h:155

◆ itemoffcompare()

static int itemoffcompare ( const void *  itemidp1,
const void *  itemidp2 
)
static

Definition at line 429 of file bufpage.c.

Referenced by compactify_tuples().

430 {
431  /* Sort in decreasing itemoff order */
432  return ((itemIdSort) itemidp2)->itemoff -
433  ((itemIdSort) itemidp1)->itemoff;
434 }
itemIdSortData * itemIdSort
Definition: bufpage.c:426

◆ PageAddItemExtended()

OffsetNumber PageAddItemExtended ( Page  page,
Item  item,
Size  size,
OffsetNumber  offsetNumber,
int  flags 
)

Definition at line 190 of file bufpage.c.

References elog, ereport, errcode(), errmsg(), InvalidOffsetNumber, ItemIdHasStorage, ItemIdIsUsed, ItemIdSetNormal, lower(), MAXALIGN, MaxHeapTuplesPerPage, memmove, OffsetNumberIsValid, OffsetNumberNext, PageClearHasFreeLinePointers, PageGetItemId, PageGetMaxOffsetNumber, PageHasFreeLinePointers, PAI_IS_HEAP, PAI_OVERWRITE, PANIC, PageHeaderData::pd_lower, PageHeaderData::pd_special, PageHeaderData::pd_upper, SizeOfPageHeaderData, upper(), VALGRIND_CHECK_MEM_IS_DEFINED, and WARNING.

195 {
196  PageHeader phdr = (PageHeader) page;
197  Size alignedSize;
198  int lower;
199  int upper;
200  ItemId itemId;
201  OffsetNumber limit;
202  bool needshuffle = false;
203 
204  /*
205  * Be wary about corrupted page pointers
206  */
207  if (phdr->pd_lower < SizeOfPageHeaderData ||
208  phdr->pd_lower > phdr->pd_upper ||
209  phdr->pd_upper > phdr->pd_special ||
210  phdr->pd_special > BLCKSZ)
211  ereport(PANIC,
212  (errcode(ERRCODE_DATA_CORRUPTED),
213  errmsg("corrupted page pointers: lower = %u, upper = %u, special = %u",
214  phdr->pd_lower, phdr->pd_upper, phdr->pd_special)));
215 
216  /*
217  * Select offsetNumber to place the new item at
218  */
220 
221  /* was offsetNumber passed in? */
222  if (OffsetNumberIsValid(offsetNumber))
223  {
224  /* yes, check it */
225  if ((flags & PAI_OVERWRITE) != 0)
226  {
227  if (offsetNumber < limit)
228  {
229  itemId = PageGetItemId(phdr, offsetNumber);
230  if (ItemIdIsUsed(itemId) || ItemIdHasStorage(itemId))
231  {
232  elog(WARNING, "will not overwrite a used ItemId");
233  return InvalidOffsetNumber;
234  }
235  }
236  }
237  else
238  {
239  if (offsetNumber < limit)
240  needshuffle = true; /* need to move existing linp's */
241  }
242  }
243  else
244  {
245  /* offsetNumber was not passed in, so find a free slot */
246  /* if no free slot, we'll put it at limit (1st open slot) */
247  if (PageHasFreeLinePointers(phdr))
248  {
249  /*
250  * Look for "recyclable" (unused) ItemId. We check for no storage
251  * as well, just to be paranoid --- unused items should never have
252  * storage.
253  */
254  for (offsetNumber = 1; offsetNumber < limit; offsetNumber++)
255  {
256  itemId = PageGetItemId(phdr, offsetNumber);
257  if (!ItemIdIsUsed(itemId) && !ItemIdHasStorage(itemId))
258  break;
259  }
260  if (offsetNumber >= limit)
261  {
262  /* the hint is wrong, so reset it */
264  }
265  }
266  else
267  {
268  /* don't bother searching if hint says there's no free slot */
269  offsetNumber = limit;
270  }
271  }
272 
273  /* Reject placing items beyond the first unused line pointer */
274  if (offsetNumber > limit)
275  {
276  elog(WARNING, "specified item offset is too large");
277  return InvalidOffsetNumber;
278  }
279 
280  /* Reject placing items beyond heap boundary, if heap */
281  if ((flags & PAI_IS_HEAP) != 0 && offsetNumber > MaxHeapTuplesPerPage)
282  {
283  elog(WARNING, "can't put more than MaxHeapTuplesPerPage items in a heap page");
284  return InvalidOffsetNumber;
285  }
286 
287  /*
288  * Compute new lower and upper pointers for page, see if it'll fit.
289  *
290  * Note: do arithmetic as signed ints, to avoid mistakes if, say,
291  * alignedSize > pd_upper.
292  */
293  if (offsetNumber == limit || needshuffle)
294  lower = phdr->pd_lower + sizeof(ItemIdData);
295  else
296  lower = phdr->pd_lower;
297 
298  alignedSize = MAXALIGN(size);
299 
300  upper = (int) phdr->pd_upper - (int) alignedSize;
301 
302  if (lower > upper)
303  return InvalidOffsetNumber;
304 
305  /*
306  * OK to insert the item. First, shuffle the existing pointers if needed.
307  */
308  itemId = PageGetItemId(phdr, offsetNumber);
309 
310  if (needshuffle)
311  memmove(itemId + 1, itemId,
312  (limit - offsetNumber) * sizeof(ItemIdData));
313 
314  /* set the item pointer */
315  ItemIdSetNormal(itemId, upper, size);
316 
317  /*
318  * Items normally contain no uninitialized bytes. Core bufpage consumers
319  * conform, but this is not a necessary coding rule; a new index AM could
320  * opt to depart from it. However, data type input functions and other
321  * C-language functions that synthesize datums should initialize all
322  * bytes; datumIsEqual() relies on this. Testing here, along with the
323  * similar check in printtup(), helps to catch such mistakes.
324  *
325  * Values of the "name" type retrieved via index-only scans may contain
326  * uninitialized bytes; see comment in btrescan(). Valgrind will report
327  * this as an error, but it is safe to ignore.
328  */
329  VALGRIND_CHECK_MEM_IS_DEFINED(item, size);
330 
331  /* copy the item's data onto the page */
332  memcpy((char *) page + upper, item, size);
333 
334  /* adjust page header */
335  phdr->pd_lower = (LocationIndex) lower;
336  phdr->pd_upper = (LocationIndex) upper;
337 
338  return offsetNumber;
339 }
#define PageClearHasFreeLinePointers(page)
Definition: bufpage.h:371
Datum lower(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:43
#define VALGRIND_CHECK_MEM_IS_DEFINED(addr, size)
Definition: memdebug.h:23
#define PAI_OVERWRITE
Definition: bufpage.h:409
#define ItemIdIsUsed(itemId)
Definition: itemid.h:91
#define MaxHeapTuplesPerPage
Definition: htup_details.h:580
int errcode(int sqlerrcode)
Definition: elog.c:575
Datum upper(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:74
#define SizeOfPageHeaderData
Definition: bufpage.h:212
#define PANIC
Definition: elog.h:53
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:353
uint16 OffsetNumber
Definition: off.h:24
#define ItemIdSetNormal(itemId, off, len)
Definition: itemid.h:139
#define memmove(d, s, c)
Definition: c.h:1045
struct ItemIdData ItemIdData
#define ereport(elevel, rest)
Definition: elog.h:122
LocationIndex pd_special
Definition: bufpage.h:156
#define WARNING
Definition: elog.h:40
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:231
uint16 LocationIndex
Definition: bufpage.h:83
#define InvalidOffsetNumber
Definition: off.h:26
#define ItemIdHasStorage(itemId)
Definition: itemid.h:119
PageHeaderData * PageHeader
Definition: bufpage.h:162
#define OffsetNumberNext(offsetNumber)
Definition: off.h:53
size_t Size
Definition: c.h:404
#define MAXALIGN(LEN)
Definition: c.h:623
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define PAI_IS_HEAP
Definition: bufpage.h:410
#define OffsetNumberIsValid(offsetNumber)
Definition: off.h:40
#define PageHasFreeLinePointers(page)
Definition: bufpage.h:367
#define elog
Definition: elog.h:219
LocationIndex pd_upper
Definition: bufpage.h:155
LocationIndex pd_lower
Definition: bufpage.h:154

◆ PageGetExactFreeSpace()

Size PageGetExactFreeSpace ( Page  page)

Definition at line 629 of file bufpage.c.

Referenced by _bt_findsplitloc(), allocNewBuffer(), brin_can_do_samepage_update(), doPickSplit(), GetHashPageStats(), ginHeapTupleFastInsert(), spgAddNodeAction(), SpGistGetBuffer(), SpGistPageAddNewItem(), SpGistSetLastUsedPage(), and writeListPage().

630 {
631  int space;
632 
633  /*
634  * Use signed arithmetic here so that we behave sensibly if pd_lower >
635  * pd_upper.
636  */
637  space = (int) ((PageHeader) page)->pd_upper -
638  (int) ((PageHeader) page)->pd_lower;
639 
640  if (space < 0)
641  return 0;
642 
643  return (Size) space;
644 }
PageHeaderData * PageHeader
Definition: bufpage.h:162
size_t Size
Definition: c.h:404

◆ PageGetFreeSpace()

Size PageGetFreeSpace ( Page  page)

Definition at line 578 of file bufpage.c.

Referenced by _bt_buildadd(), _bt_findinsertloc(), _bt_insertonpg(), _hash_doinsert(), br_page_get_freespace(), entryIsEnoughSpace(), GetBTPageStatistics(), GetHashPageStatistics(), gistnospace(), PageGetHeapFreeSpace(), pgstat_index_page(), pgstatindex_impl(), and terminate_brin_buildstate().

579 {
580  int space;
581 
582  /*
583  * Use signed arithmetic here so that we behave sensibly if pd_lower >
584  * pd_upper.
585  */
586  space = (int) ((PageHeader) page)->pd_upper -
587  (int) ((PageHeader) page)->pd_lower;
588 
589  if (space < (int) sizeof(ItemIdData))
590  return 0;
591  space -= sizeof(ItemIdData);
592 
593  return (Size) space;
594 }
struct ItemIdData ItemIdData
PageHeaderData * PageHeader
Definition: bufpage.h:162
size_t Size
Definition: c.h:404

◆ PageGetFreeSpaceForMultipleTuples()

Size PageGetFreeSpaceForMultipleTuples ( Page  page,
int  ntups 
)

Definition at line 605 of file bufpage.c.

Referenced by _hash_splitbucket(), and _hash_squeezebucket().

606 {
607  int space;
608 
609  /*
610  * Use signed arithmetic here so that we behave sensibly if pd_lower >
611  * pd_upper.
612  */
613  space = (int) ((PageHeader) page)->pd_upper -
614  (int) ((PageHeader) page)->pd_lower;
615 
616  if (space < (int) (ntups * sizeof(ItemIdData)))
617  return 0;
618  space -= ntups * sizeof(ItemIdData);
619 
620  return (Size) space;
621 }
struct ItemIdData ItemIdData
PageHeaderData * PageHeader
Definition: bufpage.h:162
size_t Size
Definition: c.h:404

◆ PageGetHeapFreeSpace()

Size PageGetHeapFreeSpace ( Page  page)

Definition at line 662 of file bufpage.c.

References FirstOffsetNumber, ItemIdIsUsed, MaxHeapTuplesPerPage, OffsetNumberNext, PageGetFreeSpace(), PageGetItemId, PageGetMaxOffsetNumber, and PageHasFreeLinePointers.

Referenced by heap_multi_insert(), heap_page_prune_opt(), heap_update(), heap_xlog_clean(), heap_xlog_insert(), heap_xlog_multi_insert(), heap_xlog_update(), lazy_scan_heap(), lazy_vacuum_heap(), pgstat_heap(), raw_heap_insert(), RelationAddExtraBlocks(), RelationGetBufferForTuple(), and statapprox_heap().

663 {
664  Size space;
665 
666  space = PageGetFreeSpace(page);
667  if (space > 0)
668  {
669  OffsetNumber offnum,
670  nline;
671 
672  /*
673  * Are there already MaxHeapTuplesPerPage line pointers in the page?
674  */
675  nline = PageGetMaxOffsetNumber(page);
676  if (nline >= MaxHeapTuplesPerPage)
677  {
679  {
680  /*
681  * Since this is just a hint, we must confirm that there is
682  * indeed a free line pointer
683  */
684  for (offnum = FirstOffsetNumber; offnum <= nline; offnum = OffsetNumberNext(offnum))
685  {
686  ItemId lp = PageGetItemId(page, offnum);
687 
688  if (!ItemIdIsUsed(lp))
689  break;
690  }
691 
692  if (offnum > nline)
693  {
694  /*
695  * The hint is wrong, but we can't clear it here since we
696  * don't have the ability to mark the page dirty.
697  */
698  space = 0;
699  }
700  }
701  else
702  {
703  /*
704  * Although the hint might be wrong, PageAddItem will believe
705  * it anyway, so we must believe it too.
706  */
707  space = 0;
708  }
709  }
710  }
711  return space;
712 }
#define ItemIdIsUsed(itemId)
Definition: itemid.h:91
#define MaxHeapTuplesPerPage
Definition: htup_details.h:580
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:353
Size PageGetFreeSpace(Page page)
Definition: bufpage.c:578
uint16 OffsetNumber
Definition: off.h:24
#define FirstOffsetNumber
Definition: off.h:27
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:231
#define OffsetNumberNext(offsetNumber)
Definition: off.h:53
size_t Size
Definition: c.h:404
#define PageHasFreeLinePointers(page)
Definition: bufpage.h:367

◆ PageGetTempPage()

Page PageGetTempPage ( Page  page)

Definition at line 348 of file bufpage.c.

References PageGetPageSize, and palloc().

Referenced by _bt_split(), dataSplitPageInternal(), and ginPlaceToPage().

349 {
350  Size pageSize;
351  Page temp;
352 
353  pageSize = PageGetPageSize(page);
354  temp = (Page) palloc(pageSize);
355 
356  return temp;
357 }
#define PageGetPageSize(page)
Definition: bufpage.h:264
size_t Size
Definition: c.h:404
void * palloc(Size size)
Definition: mcxt.c:848
Pointer Page
Definition: bufpage.h:74

◆ PageGetTempPageCopy()

Page PageGetTempPageCopy ( Page  page)

Definition at line 365 of file bufpage.c.

References PageGetPageSize, and palloc().

Referenced by entrySplitPage(), and ginVacuumEntryPage().

366 {
367  Size pageSize;
368  Page temp;
369 
370  pageSize = PageGetPageSize(page);
371  temp = (Page) palloc(pageSize);
372 
373  memcpy(temp, page, pageSize);
374 
375  return temp;
376 }
#define PageGetPageSize(page)
Definition: bufpage.h:264
size_t Size
Definition: c.h:404
void * palloc(Size size)
Definition: mcxt.c:848
Pointer Page
Definition: bufpage.h:74

◆ PageGetTempPageCopySpecial()

Page PageGetTempPageCopySpecial ( Page  page)

Definition at line 385 of file bufpage.c.

References PageGetPageSize, PageGetSpecialPointer, PageGetSpecialSize, PageInit(), and palloc().

Referenced by btree_xlog_split(), and gistplacetopage().

386 {
387  Size pageSize;
388  Page temp;
389 
390  pageSize = PageGetPageSize(page);
391  temp = (Page) palloc(pageSize);
392 
393  PageInit(temp, pageSize, PageGetSpecialSize(page));
394  memcpy(PageGetSpecialPointer(temp),
395  PageGetSpecialPointer(page),
396  PageGetSpecialSize(page));
397 
398  return temp;
399 }
#define PageGetPageSize(page)
Definition: bufpage.h:264
size_t Size
Definition: c.h:404
#define PageGetSpecialPointer(page)
Definition: bufpage.h:322
#define PageGetSpecialSize(page)
Definition: bufpage.h:296
void * palloc(Size size)
Definition: mcxt.c:848
Pointer Page
Definition: bufpage.h:74
void PageInit(Page page, Size pageSize, Size specialSize)
Definition: bufpage.c:41

◆ PageIndexMultiDelete()

void PageIndexMultiDelete ( Page  page,
OffsetNumber itemnos,
int  nitems 
)

Definition at line 832 of file bufpage.c.

References itemIdSortData::alignedlen, Assert, compactify_tuples(), elog, ereport, errcode(), errmsg(), ERROR, FirstOffsetNumber, ItemIdGetLength, ItemIdGetOffset, ItemIdHasStorage, itemIdSortData::itemoff, MAXALIGN, MaxIndexTuplesPerPage, itemIdSortData::offsetindex, OffsetNumberNext, PageGetItemId, PageGetMaxOffsetNumber, PageIndexTupleDelete(), PageHeaderData::pd_linp, PageHeaderData::pd_lower, PageHeaderData::pd_special, PageHeaderData::pd_upper, and SizeOfPageHeaderData.

Referenced by _bt_delitems_delete(), _bt_delitems_vacuum(), _hash_squeezebucket(), _hash_vacuum_one_page(), btree_xlog_delete(), btree_xlog_vacuum(), gistbulkdelete(), gistRedoPageUpdateRecord(), gistvacuumpage(), hash_xlog_delete(), hash_xlog_move_page_contents(), hash_xlog_vacuum_one_page(), hashbucketcleanup(), spgPageIndexMultiDelete(), spgRedoVacuumRedirect(), spgRedoVacuumRoot(), vacuumLeafRoot(), and vacuumRedirectAndPlaceholder().

833 {
834  PageHeader phdr = (PageHeader) page;
835  Offset pd_lower = phdr->pd_lower;
836  Offset pd_upper = phdr->pd_upper;
837  Offset pd_special = phdr->pd_special;
839  ItemIdData newitemids[MaxIndexTuplesPerPage];
840  itemIdSort itemidptr;
841  ItemId lp;
842  int nline,
843  nused;
844  Size totallen;
845  Size size;
846  unsigned offset;
847  int nextitm;
848  OffsetNumber offnum;
849 
850  Assert(nitems <= MaxIndexTuplesPerPage);
851 
852  /*
853  * If there aren't very many items to delete, then retail
854  * PageIndexTupleDelete is the best way. Delete the items in reverse
855  * order so we don't have to think about adjusting item numbers for
856  * previous deletions.
857  *
858  * TODO: tune the magic number here
859  */
860  if (nitems <= 2)
861  {
862  while (--nitems >= 0)
863  PageIndexTupleDelete(page, itemnos[nitems]);
864  return;
865  }
866 
867  /*
868  * As with PageRepairFragmentation, paranoia seems justified.
869  */
870  if (pd_lower < SizeOfPageHeaderData ||
871  pd_lower > pd_upper ||
872  pd_upper > pd_special ||
873  pd_special > BLCKSZ ||
874  pd_special != MAXALIGN(pd_special))
875  ereport(ERROR,
876  (errcode(ERRCODE_DATA_CORRUPTED),
877  errmsg("corrupted page pointers: lower = %u, upper = %u, special = %u",
878  pd_lower, pd_upper, pd_special)));
879 
880  /*
881  * Scan the item pointer array and build a list of just the ones we are
882  * going to keep. Notice we do not modify the page yet, since we are
883  * still validity-checking.
884  */
885  nline = PageGetMaxOffsetNumber(page);
886  itemidptr = itemidbase;
887  totallen = 0;
888  nused = 0;
889  nextitm = 0;
890  for (offnum = FirstOffsetNumber; offnum <= nline; offnum = OffsetNumberNext(offnum))
891  {
892  lp = PageGetItemId(page, offnum);
894  size = ItemIdGetLength(lp);
895  offset = ItemIdGetOffset(lp);
896  if (offset < pd_upper ||
897  (offset + size) > pd_special ||
898  offset != MAXALIGN(offset))
899  ereport(ERROR,
900  (errcode(ERRCODE_DATA_CORRUPTED),
901  errmsg("corrupted item pointer: offset = %u, length = %u",
902  offset, (unsigned int) size)));
903 
904  if (nextitm < nitems && offnum == itemnos[nextitm])
905  {
906  /* skip item to be deleted */
907  nextitm++;
908  }
909  else
910  {
911  itemidptr->offsetindex = nused; /* where it will go */
912  itemidptr->itemoff = offset;
913  itemidptr->alignedlen = MAXALIGN(size);
914  totallen += itemidptr->alignedlen;
915  newitemids[nused] = *lp;
916  itemidptr++;
917  nused++;
918  }
919  }
920 
921  /* this will catch invalid or out-of-order itemnos[] */
922  if (nextitm != nitems)
923  elog(ERROR, "incorrect index offsets supplied");
924 
925  if (totallen > (Size) (pd_special - pd_lower))
926  ereport(ERROR,
927  (errcode(ERRCODE_DATA_CORRUPTED),
928  errmsg("corrupted item lengths: total %u, available space %u",
929  (unsigned int) totallen, pd_special - pd_lower)));
930 
931  /*
932  * Looks good. Overwrite the line pointers with the copy, from which we've
933  * removed all the unused items.
934  */
935  memcpy(phdr->pd_linp, newitemids, nused * sizeof(ItemIdData));
936  phdr->pd_lower = SizeOfPageHeaderData + nused * sizeof(ItemIdData);
937 
938  /* and compactify the tuple data */
939  compactify_tuples(itemidbase, nused, page);
940 }
int16 itemoff
Definition: bufpage.c:423
void PageIndexTupleDelete(Page page, OffsetNumber offnum)
Definition: bufpage.c:723
int errcode(int sqlerrcode)
Definition: elog.c:575
#define SizeOfPageHeaderData
Definition: bufpage.h:212
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:353
uint16 alignedlen
Definition: bufpage.c:424
uint16 offsetindex
Definition: bufpage.c:422
uint16 OffsetNumber
Definition: off.h:24
#define ItemIdGetLength(itemId)
Definition: itemid.h:58
#define ERROR
Definition: elog.h:43
#define FirstOffsetNumber
Definition: off.h:27
struct ItemIdData ItemIdData
#define ItemIdGetOffset(itemId)
Definition: itemid.h:64
#define ereport(elevel, rest)
Definition: elog.h:122
static void compactify_tuples(itemIdSort itemidbase, int nitems, Page page)
Definition: bufpage.c:441
LocationIndex pd_special
Definition: bufpage.h:156
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:231
#define ItemIdHasStorage(itemId)
Definition: itemid.h:119
PageHeaderData * PageHeader
Definition: bufpage.h:162
#define Assert(condition)
Definition: c.h:670
signed int Offset
Definition: c.h:423
#define OffsetNumberNext(offsetNumber)
Definition: off.h:53
size_t Size
Definition: c.h:404
#define MAXALIGN(LEN)
Definition: c.h:623
#define MaxIndexTuplesPerPage
Definition: itup.h:137
int errmsg(const char *fmt,...)
Definition: elog.c:797
ItemIdData pd_linp[FLEXIBLE_ARRAY_MEMBER]
Definition: bufpage.h:159
#define elog
Definition: elog.h:219
LocationIndex pd_upper
Definition: bufpage.h:155
LocationIndex pd_lower
Definition: bufpage.h:154

◆ PageIndexTupleDelete()

void PageIndexTupleDelete ( Page  page,
OffsetNumber  offnum 
)

Definition at line 723 of file bufpage.c.

References Assert, elog, ereport, errcode(), errmsg(), ERROR, i, ItemIdGetLength, ItemIdGetOffset, ItemIdHasStorage, ItemIdData::lp_off, MAXALIGN, memmove, PageGetItemId, PageGetMaxOffsetNumber, PageIsEmpty, PageHeaderData::pd_linp, PageHeaderData::pd_lower, PageHeaderData::pd_special, PageHeaderData::pd_upper, and SizeOfPageHeaderData.

Referenced by _bt_mark_page_halfdead(), addLeafTuple(), addOrReplaceTuple(), btree_xlog_mark_page_halfdead(), entryPreparePage(), ginRedoInsertEntry(), ginVacuumEntryPage(), gistplacetopage(), PageIndexMultiDelete(), spgAddNodeAction(), SpGistPageAddNewItem(), spgRedoAddLeaf(), spgRedoAddNode(), spgRedoSplitTuple(), and spgSplitNodeAction().

724 {
725  PageHeader phdr = (PageHeader) page;
726  char *addr;
727  ItemId tup;
728  Size size;
729  unsigned offset;
730  int nbytes;
731  int offidx;
732  int nline;
733 
734  /*
735  * As with PageRepairFragmentation, paranoia seems justified.
736  */
737  if (phdr->pd_lower < SizeOfPageHeaderData ||
738  phdr->pd_lower > phdr->pd_upper ||
739  phdr->pd_upper > phdr->pd_special ||
740  phdr->pd_special > BLCKSZ ||
741  phdr->pd_special != MAXALIGN(phdr->pd_special))
742  ereport(ERROR,
743  (errcode(ERRCODE_DATA_CORRUPTED),
744  errmsg("corrupted page pointers: lower = %u, upper = %u, special = %u",
745  phdr->pd_lower, phdr->pd_upper, phdr->pd_special)));
746 
747  nline = PageGetMaxOffsetNumber(page);
748  if ((int) offnum <= 0 || (int) offnum > nline)
749  elog(ERROR, "invalid index offnum: %u", offnum);
750 
751  /* change offset number to offset index */
752  offidx = offnum - 1;
753 
754  tup = PageGetItemId(page, offnum);
755  Assert(ItemIdHasStorage(tup));
756  size = ItemIdGetLength(tup);
757  offset = ItemIdGetOffset(tup);
758 
759  if (offset < phdr->pd_upper || (offset + size) > phdr->pd_special ||
760  offset != MAXALIGN(offset))
761  ereport(ERROR,
762  (errcode(ERRCODE_DATA_CORRUPTED),
763  errmsg("corrupted item pointer: offset = %u, size = %u",
764  offset, (unsigned int) size)));
765 
766  /* Amount of space to actually be deleted */
767  size = MAXALIGN(size);
768 
769  /*
770  * First, we want to get rid of the pd_linp entry for the index tuple. We
771  * copy all subsequent linp's back one slot in the array. We don't use
772  * PageGetItemId, because we are manipulating the _array_, not individual
773  * linp's.
774  */
775  nbytes = phdr->pd_lower -
776  ((char *) &phdr->pd_linp[offidx + 1] - (char *) phdr);
777 
778  if (nbytes > 0)
779  memmove((char *) &(phdr->pd_linp[offidx]),
780  (char *) &(phdr->pd_linp[offidx + 1]),
781  nbytes);
782 
783  /*
784  * Now move everything between the old upper bound (beginning of tuple
785  * space) and the beginning of the deleted tuple forward, so that space in
786  * the middle of the page is left free. If we've just deleted the tuple
787  * at the beginning of tuple space, then there's no need to do the copy.
788  */
789 
790  /* beginning of tuple space */
791  addr = (char *) page + phdr->pd_upper;
792 
793  if (offset > phdr->pd_upper)
794  memmove(addr + size, addr, offset - phdr->pd_upper);
795 
796  /* adjust free space boundary pointers */
797  phdr->pd_upper += size;
798  phdr->pd_lower -= sizeof(ItemIdData);
799 
800  /*
801  * Finally, we need to adjust the linp entries that remain.
802  *
803  * Anything that used to be before the deleted tuple's data was moved
804  * forward by the size of the deleted tuple.
805  */
806  if (!PageIsEmpty(page))
807  {
808  int i;
809 
810  nline--; /* there's one less than when we started */
811  for (i = 1; i <= nline; i++)
812  {
813  ItemId ii = PageGetItemId(phdr, i);
814 
816  if (ItemIdGetOffset(ii) <= offset)
817  ii->lp_off += size;
818  }
819  }
820 }
#define PageIsEmpty(page)
Definition: bufpage.h:218
int errcode(int sqlerrcode)
Definition: elog.c:575
#define SizeOfPageHeaderData
Definition: bufpage.h:212
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:353
#define ItemIdGetLength(itemId)
Definition: itemid.h:58
#define ERROR
Definition: elog.h:43
#define memmove(d, s, c)
Definition: c.h:1045
struct ItemIdData ItemIdData
#define ItemIdGetOffset(itemId)
Definition: itemid.h:64
#define ereport(elevel, rest)
Definition: elog.h:122
LocationIndex pd_special
Definition: bufpage.h:156
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:231
unsigned lp_off
Definition: itemid.h:26
#define ItemIdHasStorage(itemId)
Definition: itemid.h:119
PageHeaderData * PageHeader
Definition: bufpage.h:162
#define Assert(condition)
Definition: c.h:670
size_t Size
Definition: c.h:404
#define MAXALIGN(LEN)
Definition: c.h:623
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
ItemIdData pd_linp[FLEXIBLE_ARRAY_MEMBER]
Definition: bufpage.h:159
#define elog
Definition: elog.h:219
LocationIndex pd_upper
Definition: bufpage.h:155
LocationIndex pd_lower
Definition: bufpage.h:154

◆ PageIndexTupleDeleteNoCompact()

void PageIndexTupleDeleteNoCompact ( Page  page,
OffsetNumber  offnum 
)

Definition at line 954 of file bufpage.c.

References Assert, elog, ereport, errcode(), errmsg(), ERROR, i, ItemIdGetLength, ItemIdGetOffset, ItemIdHasStorage, ItemIdSetUnused, ItemIdData::lp_off, MAXALIGN, memmove, PageGetItemId, PageGetMaxOffsetNumber, PageIsEmpty, PageHeaderData::pd_lower, PageHeaderData::pd_special, PageHeaderData::pd_upper, and SizeOfPageHeaderData.

Referenced by brin_doupdate(), brin_xlog_desummarize_page(), brin_xlog_update(), and brinRevmapDesummarizeRange().

955 {
956  PageHeader phdr = (PageHeader) page;
957  char *addr;
958  ItemId tup;
959  Size size;
960  unsigned offset;
961  int nline;
962 
963  /*
964  * As with PageRepairFragmentation, paranoia seems justified.
965  */
966  if (phdr->pd_lower < SizeOfPageHeaderData ||
967  phdr->pd_lower > phdr->pd_upper ||
968  phdr->pd_upper > phdr->pd_special ||
969  phdr->pd_special > BLCKSZ ||
970  phdr->pd_special != MAXALIGN(phdr->pd_special))
971  ereport(ERROR,
972  (errcode(ERRCODE_DATA_CORRUPTED),
973  errmsg("corrupted page pointers: lower = %u, upper = %u, special = %u",
974  phdr->pd_lower, phdr->pd_upper, phdr->pd_special)));
975 
976  nline = PageGetMaxOffsetNumber(page);
977  if ((int) offnum <= 0 || (int) offnum > nline)
978  elog(ERROR, "invalid index offnum: %u", offnum);
979 
980  tup = PageGetItemId(page, offnum);
981  Assert(ItemIdHasStorage(tup));
982  size = ItemIdGetLength(tup);
983  offset = ItemIdGetOffset(tup);
984 
985  if (offset < phdr->pd_upper || (offset + size) > phdr->pd_special ||
986  offset != MAXALIGN(offset))
987  ereport(ERROR,
988  (errcode(ERRCODE_DATA_CORRUPTED),
989  errmsg("corrupted item pointer: offset = %u, size = %u",
990  offset, (unsigned int) size)));
991 
992  /* Amount of space to actually be deleted */
993  size = MAXALIGN(size);
994 
995  /*
996  * Either set the item pointer to "unused", or zap it if it's the last
997  * one. (Note: it's possible that the next-to-last one(s) are already
998  * unused, but we do not trouble to try to compact them out if so.)
999  */
1000  if ((int) offnum < nline)
1001  ItemIdSetUnused(tup);
1002  else
1003  {
1004  phdr->pd_lower -= sizeof(ItemIdData);
1005  nline--; /* there's one less than when we started */
1006  }
1007 
1008  /*
1009  * Now move everything between the old upper bound (beginning of tuple
1010  * space) and the beginning of the deleted tuple forward, so that space in
1011  * the middle of the page is left free. If we've just deleted the tuple
1012  * at the beginning of tuple space, then there's no need to do the copy.
1013  */
1014 
1015  /* beginning of tuple space */
1016  addr = (char *) page + phdr->pd_upper;
1017 
1018  if (offset > phdr->pd_upper)
1019  memmove(addr + size, addr, offset - phdr->pd_upper);
1020 
1021  /* adjust free space boundary pointer */
1022  phdr->pd_upper += size;
1023 
1024  /*
1025  * Finally, we need to adjust the linp entries that remain.
1026  *
1027  * Anything that used to be before the deleted tuple's data was moved
1028  * forward by the size of the deleted tuple.
1029  */
1030  if (!PageIsEmpty(page))
1031  {
1032  int i;
1033 
1034  for (i = 1; i <= nline; i++)
1035  {
1036  ItemId ii = PageGetItemId(phdr, i);
1037 
1038  if (ItemIdHasStorage(ii) && ItemIdGetOffset(ii) <= offset)
1039  ii->lp_off += size;
1040  }
1041  }
1042 }
#define PageIsEmpty(page)
Definition: bufpage.h:218
int errcode(int sqlerrcode)
Definition: elog.c:575
#define SizeOfPageHeaderData
Definition: bufpage.h:212
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:353
#define ItemIdGetLength(itemId)
Definition: itemid.h:58
#define ERROR
Definition: elog.h:43
#define memmove(d, s, c)
Definition: c.h:1045
struct ItemIdData ItemIdData
#define ItemIdGetOffset(itemId)
Definition: itemid.h:64
#define ereport(elevel, rest)
Definition: elog.h:122
LocationIndex pd_special
Definition: bufpage.h:156
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:231
unsigned lp_off
Definition: itemid.h:26
#define ItemIdHasStorage(itemId)
Definition: itemid.h:119
PageHeaderData * PageHeader
Definition: bufpage.h:162
#define Assert(condition)
Definition: c.h:670
size_t Size
Definition: c.h:404
#define MAXALIGN(LEN)
Definition: c.h:623
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
#define elog
Definition: elog.h:219
LocationIndex pd_upper
Definition: bufpage.h:155
#define ItemIdSetUnused(itemId)
Definition: itemid.h:127
LocationIndex pd_lower
Definition: bufpage.h:154

◆ PageIndexTupleOverwrite()

bool PageIndexTupleOverwrite ( Page  page,
OffsetNumber  offnum,
Item  newtup,
Size  newsize 
)

Definition at line 1062 of file bufpage.c.

References Assert, elog, ereport, errcode(), errmsg(), ERROR, FirstOffsetNumber, i, ItemIdGetLength, ItemIdGetOffset, ItemIdHasStorage, ItemIdSetNormal, ItemIdData::lp_off, MAXALIGN, memmove, PageGetItem, PageGetItemId, PageGetMaxOffsetNumber, PageHeaderData::pd_lower, PageHeaderData::pd_special, PageHeaderData::pd_upper, and SizeOfPageHeaderData.

Referenced by brin_doupdate(), brin_xlog_samepage_update(), gistplacetopage(), and gistRedoPageUpdateRecord().

1064 {
1065  PageHeader phdr = (PageHeader) page;
1066  ItemId tupid;
1067  int oldsize;
1068  unsigned offset;
1069  Size alignednewsize;
1070  int size_diff;
1071  int itemcount;
1072 
1073  /*
1074  * As with PageRepairFragmentation, paranoia seems justified.
1075  */
1076  if (phdr->pd_lower < SizeOfPageHeaderData ||
1077  phdr->pd_lower > phdr->pd_upper ||
1078  phdr->pd_upper > phdr->pd_special ||
1079  phdr->pd_special > BLCKSZ ||
1080  phdr->pd_special != MAXALIGN(phdr->pd_special))
1081  ereport(ERROR,
1082  (errcode(ERRCODE_DATA_CORRUPTED),
1083  errmsg("corrupted page pointers: lower = %u, upper = %u, special = %u",
1084  phdr->pd_lower, phdr->pd_upper, phdr->pd_special)));
1085 
1086  itemcount = PageGetMaxOffsetNumber(page);
1087  if ((int) offnum <= 0 || (int) offnum > itemcount)
1088  elog(ERROR, "invalid index offnum: %u", offnum);
1089 
1090  tupid = PageGetItemId(page, offnum);
1091  Assert(ItemIdHasStorage(tupid));
1092  oldsize = ItemIdGetLength(tupid);
1093  offset = ItemIdGetOffset(tupid);
1094 
1095  if (offset < phdr->pd_upper || (offset + oldsize) > phdr->pd_special ||
1096  offset != MAXALIGN(offset))
1097  ereport(ERROR,
1098  (errcode(ERRCODE_DATA_CORRUPTED),
1099  errmsg("corrupted item pointer: offset = %u, size = %u",
1100  offset, (unsigned int) oldsize)));
1101 
1102  /*
1103  * Determine actual change in space requirement, check for page overflow.
1104  */
1105  oldsize = MAXALIGN(oldsize);
1106  alignednewsize = MAXALIGN(newsize);
1107  if (alignednewsize > oldsize + (phdr->pd_upper - phdr->pd_lower))
1108  return false;
1109 
1110  /*
1111  * Relocate existing data and update line pointers, unless the new tuple
1112  * is the same size as the old (after alignment), in which case there's
1113  * nothing to do. Notice that what we have to relocate is data before the
1114  * target tuple, not data after, so it's convenient to express size_diff
1115  * as the amount by which the tuple's size is decreasing, making it the
1116  * delta to add to pd_upper and affected line pointers.
1117  */
1118  size_diff = oldsize - (int) alignednewsize;
1119  if (size_diff != 0)
1120  {
1121  char *addr = (char *) page + phdr->pd_upper;
1122  int i;
1123 
1124  /* relocate all tuple data before the target tuple */
1125  memmove(addr + size_diff, addr, offset - phdr->pd_upper);
1126 
1127  /* adjust free space boundary pointer */
1128  phdr->pd_upper += size_diff;
1129 
1130  /* adjust affected line pointers too */
1131  for (i = FirstOffsetNumber; i <= itemcount; i++)
1132  {
1133  ItemId ii = PageGetItemId(phdr, i);
1134 
1135  /* Allow items without storage; currently only BRIN needs that */
1136  if (ItemIdHasStorage(ii) && ItemIdGetOffset(ii) <= offset)
1137  ii->lp_off += size_diff;
1138  }
1139  }
1140 
1141  /* Update the item's tuple length (other fields shouldn't change) */
1142  ItemIdSetNormal(tupid, offset + size_diff, newsize);
1143 
1144  /* Copy new tuple data onto page */
1145  memcpy(PageGetItem(page, tupid), newtup, newsize);
1146 
1147  return true;
1148 }
int errcode(int sqlerrcode)
Definition: elog.c:575
#define SizeOfPageHeaderData
Definition: bufpage.h:212
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:353
#define ItemIdGetLength(itemId)
Definition: itemid.h:58
#define ERROR
Definition: elog.h:43
#define ItemIdSetNormal(itemId, off, len)
Definition: itemid.h:139
#define memmove(d, s, c)
Definition: c.h:1045
#define FirstOffsetNumber
Definition: off.h:27
#define ItemIdGetOffset(itemId)
Definition: itemid.h:64
#define ereport(elevel, rest)
Definition: elog.h:122
LocationIndex pd_special
Definition: bufpage.h:156
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:231
unsigned lp_off
Definition: itemid.h:26
#define ItemIdHasStorage(itemId)
Definition: itemid.h:119
PageHeaderData * PageHeader
Definition: bufpage.h:162
#define Assert(condition)
Definition: c.h:670
size_t Size
Definition: c.h:404
#define MAXALIGN(LEN)
Definition: c.h:623
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
#define elog
Definition: elog.h:219
LocationIndex pd_upper
Definition: bufpage.h:155
#define PageGetItem(page, itemId)
Definition: bufpage.h:336
LocationIndex pd_lower
Definition: bufpage.h:154

◆ PageInit()

void PageInit ( Page  page,
Size  pageSize,
Size  specialSize 
)

Definition at line 41 of file bufpage.c.

References Assert, MAXALIGN, MemSet, PageSetPageSizeAndVersion, PageHeaderData::pd_flags, PageHeaderData::pd_lower, PageHeaderData::pd_special, PageHeaderData::pd_upper, PG_PAGE_LAYOUT_VERSION, and SizeOfPageHeaderData.

Referenced by _bt_pageinit(), _hash_pageinit(), BloomInitPage(), brin_page_init(), fill_seq_with_data(), fsm_extend(), fsm_readbuf(), GinInitPage(), GISTInitBuffer(), heap_xlog_insert(), heap_xlog_multi_insert(), heap_xlog_update(), heap_xlog_visible(), lazy_scan_heap(), PageGetTempPageCopySpecial(), raw_heap_insert(), RelationAddExtraBlocks(), RelationGetBufferForTuple(), seq_redo(), SpGistInitPage(), vm_extend(), vm_readbuf(), and XLogRecordPageWithFreeSpace().

42 {
43  PageHeader p = (PageHeader) page;
44 
45  specialSize = MAXALIGN(specialSize);
46 
47  Assert(pageSize == BLCKSZ);
48  Assert(pageSize > specialSize + SizeOfPageHeaderData);
49 
50  /* Make sure all fields of page are zero, as well as unused space */
51  MemSet(p, 0, pageSize);
52 
53  p->pd_flags = 0;
55  p->pd_upper = pageSize - specialSize;
56  p->pd_special = pageSize - specialSize;
58  /* p->pd_prune_xid = InvalidTransactionId; done by above MemSet */
59 }
uint16 pd_flags
Definition: bufpage.h:153
#define PageSetPageSizeAndVersion(page, size, version)
Definition: bufpage.h:281
#define MemSet(start, val, len)
Definition: c.h:853
#define SizeOfPageHeaderData
Definition: bufpage.h:212
#define PG_PAGE_LAYOUT_VERSION
Definition: bufpage.h:195
LocationIndex pd_special
Definition: bufpage.h:156
PageHeaderData * PageHeader
Definition: bufpage.h:162
#define Assert(condition)
Definition: c.h:670
#define MAXALIGN(LEN)
Definition: c.h:623
LocationIndex pd_upper
Definition: bufpage.h:155
LocationIndex pd_lower
Definition: bufpage.h:154

◆ PageIsVerified()

bool PageIsVerified ( Page  page,
BlockNumber  blkno 
)

Definition at line 81 of file bufpage.c.

References DataChecksumsEnabled(), ereport, errmsg(), i, ignore_checksum_failure, MAXALIGN, PageIsNew, PageHeaderData::pd_checksum, PageHeaderData::pd_flags, PageHeaderData::pd_lower, PageHeaderData::pd_special, PageHeaderData::pd_upper, PD_VALID_FLAG_BITS, pg_checksum_page(), StaticAssertStmt, and WARNING.

Referenced by copy_relation_data(), and ReadBuffer_common().

82 {
83  PageHeader p = (PageHeader) page;
84  size_t *pagebytes;
85  int i;
86  bool checksum_failure = false;
87  bool header_sane = false;
88  bool all_zeroes = false;
89  uint16 checksum = 0;
90 
91  /*
92  * Don't verify page data unless the page passes basic non-zero test
93  */
94  if (!PageIsNew(page))
95  {
97  {
98  checksum = pg_checksum_page((char *) page, blkno);
99 
100  if (checksum != p->pd_checksum)
101  checksum_failure = true;
102  }
103 
104  /*
105  * The following checks don't prove the header is correct, only that
106  * it looks sane enough to allow into the buffer pool. Later usage of
107  * the block can still reveal problems, which is why we offer the
108  * checksum option.
109  */
110  if ((p->pd_flags & ~PD_VALID_FLAG_BITS) == 0 &&
111  p->pd_lower <= p->pd_upper &&
112  p->pd_upper <= p->pd_special &&
113  p->pd_special <= BLCKSZ &&
114  p->pd_special == MAXALIGN(p->pd_special))
115  header_sane = true;
116 
117  if (header_sane && !checksum_failure)
118  return true;
119  }
120 
121  /*
122  * Check all-zeroes case. Luckily BLCKSZ is guaranteed to always be a
123  * multiple of size_t - and it's much faster to compare memory using the
124  * native word size.
125  */
126  StaticAssertStmt(BLCKSZ == (BLCKSZ / sizeof(size_t)) * sizeof(size_t),
127  "BLCKSZ has to be a multiple of sizeof(size_t)");
128 
129  all_zeroes = true;
130  pagebytes = (size_t *) page;
131  for (i = 0; i < (BLCKSZ / sizeof(size_t)); i++)
132  {
133  if (pagebytes[i] != 0)
134  {
135  all_zeroes = false;
136  break;
137  }
138  }
139 
140  if (all_zeroes)
141  return true;
142 
143  /*
144  * Throw a WARNING if the checksum fails, but only after we've checked for
145  * the all-zeroes case.
146  */
147  if (checksum_failure)
148  {
150  (ERRCODE_DATA_CORRUPTED,
151  errmsg("page verification failed, calculated checksum %u but expected %u",
152  checksum, p->pd_checksum)));
153 
154  if (header_sane && ignore_checksum_failure)
155  return true;
156  }
157 
158  return false;
159 }
uint16 pd_flags
Definition: bufpage.h:153
bool DataChecksumsEnabled(void)
Definition: xlog.c:4738
uint16 pd_checksum
Definition: bufpage.h:152
#define StaticAssertStmt(condition, errmessage)
Definition: c.h:753
unsigned short uint16
Definition: c.h:295
#define ereport(elevel, rest)
Definition: elog.h:122
LocationIndex pd_special
Definition: bufpage.h:156
#define WARNING
Definition: elog.h:40
PageHeaderData * PageHeader
Definition: bufpage.h:162
#define PD_VALID_FLAG_BITS
Definition: bufpage.h:181
#define MAXALIGN(LEN)
Definition: c.h:623
bool ignore_checksum_failure
Definition: bufpage.c:26
#define PageIsNew(page)
Definition: bufpage.h:225
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
LocationIndex pd_upper
Definition: bufpage.h:155
uint16 pg_checksum_page(char *page, BlockNumber blkno)
LocationIndex pd_lower
Definition: bufpage.h:154

◆ PageRepairFragmentation()

void PageRepairFragmentation ( Page  page)

Definition at line 479 of file bufpage.c.

References itemIdSortData::alignedlen, compactify_tuples(), ereport, errcode(), errmsg(), ERROR, FirstOffsetNumber, i, ItemIdGetLength, ItemIdGetOffset, ItemIdHasStorage, ItemIdIsUsed, ItemIdSetUnused, itemIdSortData::itemoff, MAXALIGN, MaxHeapTuplesPerPage, itemIdSortData::offsetindex, PageClearHasFreeLinePointers, PageGetItemId, PageGetMaxOffsetNumber, PageSetHasFreeLinePointers, SizeOfPageHeaderData, and unlikely.

Referenced by heap_page_prune_execute(), and lazy_vacuum_page().

480 {
481  Offset pd_lower = ((PageHeader) page)->pd_lower;
482  Offset pd_upper = ((PageHeader) page)->pd_upper;
483  Offset pd_special = ((PageHeader) page)->pd_special;
485  itemIdSort itemidptr;
486  ItemId lp;
487  int nline,
488  nstorage,
489  nunused;
490  int i;
491  Size totallen;
492 
493  /*
494  * It's worth the trouble to be more paranoid here than in most places,
495  * because we are about to reshuffle data in (what is usually) a shared
496  * disk buffer. If we aren't careful then corrupted pointers, lengths,
497  * etc could cause us to clobber adjacent disk buffers, spreading the data
498  * loss further. So, check everything.
499  */
500  if (pd_lower < SizeOfPageHeaderData ||
501  pd_lower > pd_upper ||
502  pd_upper > pd_special ||
503  pd_special > BLCKSZ ||
504  pd_special != MAXALIGN(pd_special))
505  ereport(ERROR,
506  (errcode(ERRCODE_DATA_CORRUPTED),
507  errmsg("corrupted page pointers: lower = %u, upper = %u, special = %u",
508  pd_lower, pd_upper, pd_special)));
509 
510  /*
511  * Run through the line pointer array and collect data about live items.
512  */
513  nline = PageGetMaxOffsetNumber(page);
514  itemidptr = itemidbase;
515  nunused = totallen = 0;
516  for (i = FirstOffsetNumber; i <= nline; i++)
517  {
518  lp = PageGetItemId(page, i);
519  if (ItemIdIsUsed(lp))
520  {
521  if (ItemIdHasStorage(lp))
522  {
523  itemidptr->offsetindex = i - 1;
524  itemidptr->itemoff = ItemIdGetOffset(lp);
525  if (unlikely(itemidptr->itemoff < (int) pd_upper ||
526  itemidptr->itemoff >= (int) pd_special))
527  ereport(ERROR,
528  (errcode(ERRCODE_DATA_CORRUPTED),
529  errmsg("corrupted item pointer: %u",
530  itemidptr->itemoff)));
531  itemidptr->alignedlen = MAXALIGN(ItemIdGetLength(lp));
532  totallen += itemidptr->alignedlen;
533  itemidptr++;
534  }
535  }
536  else
537  {
538  /* Unused entries should have lp_len = 0, but make sure */
539  ItemIdSetUnused(lp);
540  nunused++;
541  }
542  }
543 
544  nstorage = itemidptr - itemidbase;
545  if (nstorage == 0)
546  {
547  /* Page is completely empty, so just reset it quickly */
548  ((PageHeader) page)->pd_upper = pd_special;
549  }
550  else
551  {
552  /* Need to compact the page the hard way */
553  if (totallen > (Size) (pd_special - pd_lower))
554  ereport(ERROR,
555  (errcode(ERRCODE_DATA_CORRUPTED),
556  errmsg("corrupted item lengths: total %u, available space %u",
557  (unsigned int) totallen, pd_special - pd_lower)));
558 
559  compactify_tuples(itemidbase, nstorage, page);
560  }
561 
562  /* Set hint bit for PageAddItem */
563  if (nunused > 0)
565  else
567 }
#define PageClearHasFreeLinePointers(page)
Definition: bufpage.h:371
int16 itemoff
Definition: bufpage.c:423
#define ItemIdIsUsed(itemId)
Definition: itemid.h:91
#define MaxHeapTuplesPerPage
Definition: htup_details.h:580
int errcode(int sqlerrcode)
Definition: elog.c:575
#define SizeOfPageHeaderData
Definition: bufpage.h:212
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:353
uint16 alignedlen
Definition: bufpage.c:424
uint16 offsetindex
Definition: bufpage.c:422
#define ItemIdGetLength(itemId)
Definition: itemid.h:58
#define ERROR
Definition: elog.h:43
#define FirstOffsetNumber
Definition: off.h:27
#define ItemIdGetOffset(itemId)
Definition: itemid.h:64
#define ereport(elevel, rest)
Definition: elog.h:122
static void compactify_tuples(itemIdSort itemidbase, int nitems, Page page)
Definition: bufpage.c:441
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:231
#define ItemIdHasStorage(itemId)
Definition: itemid.h:119
PageHeaderData * PageHeader
Definition: bufpage.h:162
signed int Offset
Definition: c.h:423
size_t Size
Definition: c.h:404
#define MAXALIGN(LEN)
Definition: c.h:623
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define PageSetHasFreeLinePointers(page)
Definition: bufpage.h:369
int i
#define unlikely(x)
Definition: c.h:190
#define ItemIdSetUnused(itemId)
Definition: itemid.h:127

◆ PageRestoreTempPage()

void PageRestoreTempPage ( Page  tempPage,
Page  oldPage 
)

Definition at line 407 of file bufpage.c.

References PageGetPageSize, and pfree().

Referenced by _bt_split(), btree_xlog_split(), createPostingTree(), ginbulkdelete(), and gistplacetopage().

408 {
409  Size pageSize;
410 
411  pageSize = PageGetPageSize(tempPage);
412  memcpy((char *) oldPage, (char *) tempPage, pageSize);
413 
414  pfree(tempPage);
415 }
void pfree(void *pointer)
Definition: mcxt.c:949
#define PageGetPageSize(page)
Definition: bufpage.h:264
size_t Size
Definition: c.h:404

◆ PageSetChecksumCopy()

char* PageSetChecksumCopy ( Page  page,
BlockNumber  blkno 
)

Definition at line 1166 of file bufpage.c.

References DataChecksumsEnabled(), MemoryContextAlloc(), PageIsNew, pg_checksum_page(), and TopMemoryContext.

Referenced by FlushBuffer().

1167 {
1168  static char *pageCopy = NULL;
1169 
1170  /* If we don't need a checksum, just return the passed-in data */
1171  if (PageIsNew(page) || !DataChecksumsEnabled())
1172  return (char *) page;
1173 
1174  /*
1175  * We allocate the copy space once and use it over on each subsequent
1176  * call. The point of palloc'ing here, rather than having a static char
1177  * array, is first to ensure adequate alignment for the checksumming code
1178  * and second to avoid wasting space in processes that never call this.
1179  */
1180  if (pageCopy == NULL)
1181  pageCopy = MemoryContextAlloc(TopMemoryContext, BLCKSZ);
1182 
1183  memcpy(pageCopy, (char *) page, BLCKSZ);
1184  ((PageHeader) pageCopy)->pd_checksum = pg_checksum_page(pageCopy, blkno);
1185  return pageCopy;
1186 }
bool DataChecksumsEnabled(void)
Definition: xlog.c:4738
MemoryContext TopMemoryContext
Definition: mcxt.c:43
PageHeaderData * PageHeader
Definition: bufpage.h:162
#define PageIsNew(page)
Definition: bufpage.h:225
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:706
uint16 pg_checksum_page(char *page, BlockNumber blkno)

◆ PageSetChecksumInplace()

void PageSetChecksumInplace ( Page  page,
BlockNumber  blkno 
)

Definition at line 1195 of file bufpage.c.

References DataChecksumsEnabled(), PageIsNew, and pg_checksum_page().

Referenced by _bt_blwritepage(), blbuildempty(), btbuildempty(), copy_relation_data(), end_heap_rewrite(), FlushRelationBuffers(), fsm_extend(), LocalBufferAlloc(), raw_heap_insert(), spgbuildempty(), and vm_extend().

1196 {
1197  /* If we don't need a checksum, just return */
1198  if (PageIsNew(page) || !DataChecksumsEnabled())
1199  return;
1200 
1201  ((PageHeader) page)->pd_checksum = pg_checksum_page((char *) page, blkno);
1202 }
bool DataChecksumsEnabled(void)
Definition: xlog.c:4738
PageHeaderData * PageHeader
Definition: bufpage.h:162
#define PageIsNew(page)
Definition: bufpage.h:225
uint16 pg_checksum_page(char *page, BlockNumber blkno)

Variable Documentation

◆ ignore_checksum_failure

bool ignore_checksum_failure = false

Definition at line 26 of file bufpage.c.

Referenced by PageIsVerified().