PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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 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

Definition at line 426 of file bufpage.c.

Function Documentation

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:1058
LocationIndex pd_special
Definition: bufpage.h:156
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:232
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:372
int i
#define qsort(a, b, c, d)
Definition: port.h:440
LocationIndex pd_upper
Definition: bufpage.h:155
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
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:372
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:410
#define ItemIdIsUsed(itemId)
Definition: itemid.h:91
#define MaxHeapTuplesPerPage
Definition: htup_details.h:575
int errcode(int sqlerrcode)
Definition: elog.c:575
Datum upper(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:74
#define SizeOfPageHeaderData
Definition: bufpage.h:213
#define PANIC
Definition: elog.h:53
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:354
uint16 OffsetNumber
Definition: off.h:24
#define ItemIdSetNormal(itemId, off, len)
Definition: itemid.h:139
#define memmove(d, s, c)
Definition: c.h:1058
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:232
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:353
#define MAXALIGN(LEN)
Definition: c.h:584
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define PAI_IS_HEAP
Definition: bufpage.h:411
#define OffsetNumberIsValid(offsetNumber)
Definition: off.h:40
#define PageHasFreeLinePointers(page)
Definition: bufpage.h:368
#define elog
Definition: elog.h:219
LocationIndex pd_upper
Definition: bufpage.h:155
LocationIndex pd_lower
Definition: bufpage.h:154
Size PageGetExactFreeSpace ( Page  page)

Definition at line 606 of file bufpage.c.

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

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

Definition at line 582 of file bufpage.c.

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

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

Definition at line 639 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().

640 {
641  Size space;
642 
643  space = PageGetFreeSpace(page);
644  if (space > 0)
645  {
646  OffsetNumber offnum,
647  nline;
648 
649  /*
650  * Are there already MaxHeapTuplesPerPage line pointers in the page?
651  */
652  nline = PageGetMaxOffsetNumber(page);
653  if (nline >= MaxHeapTuplesPerPage)
654  {
656  {
657  /*
658  * Since this is just a hint, we must confirm that there is
659  * indeed a free line pointer
660  */
661  for (offnum = FirstOffsetNumber; offnum <= nline; offnum = OffsetNumberNext(offnum))
662  {
663  ItemId lp = PageGetItemId(page, offnum);
664 
665  if (!ItemIdIsUsed(lp))
666  break;
667  }
668 
669  if (offnum > nline)
670  {
671  /*
672  * The hint is wrong, but we can't clear it here since we
673  * don't have the ability to mark the page dirty.
674  */
675  space = 0;
676  }
677  }
678  else
679  {
680  /*
681  * Although the hint might be wrong, PageAddItem will believe
682  * it anyway, so we must believe it too.
683  */
684  space = 0;
685  }
686  }
687  }
688  return space;
689 }
#define ItemIdIsUsed(itemId)
Definition: itemid.h:91
#define MaxHeapTuplesPerPage
Definition: htup_details.h:575
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:354
Size PageGetFreeSpace(Page page)
Definition: bufpage.c:582
uint16 OffsetNumber
Definition: off.h:24
#define FirstOffsetNumber
Definition: off.h:27
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:232
#define OffsetNumberNext(offsetNumber)
Definition: off.h:53
size_t Size
Definition: c.h:353
#define PageHasFreeLinePointers(page)
Definition: bufpage.h:368
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:265
size_t Size
Definition: c.h:353
void * palloc(Size size)
Definition: mcxt.c:891
Pointer Page
Definition: bufpage.h:74
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:265
size_t Size
Definition: c.h:353
void * palloc(Size size)
Definition: mcxt.c:891
Pointer Page
Definition: bufpage.h:74
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:265
size_t Size
Definition: c.h:353
#define PageGetSpecialPointer(page)
Definition: bufpage.h:323
#define PageGetSpecialSize(page)
Definition: bufpage.h:297
void * palloc(Size size)
Definition: mcxt.c:891
Pointer Page
Definition: bufpage.h:74
void PageInit(Page page, Size pageSize, Size specialSize)
Definition: bufpage.c:41
void PageIndexMultiDelete ( Page  page,
OffsetNumber itemnos,
int  nitems 
)

Definition at line 809 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(), btree_xlog_delete(), btree_xlog_vacuum(), gistbulkdelete(), gistRedoPageUpdateRecord(), gistvacuumpage(), hashbucketcleanup(), spgPageIndexMultiDelete(), spgRedoVacuumRedirect(), spgRedoVacuumRoot(), vacuumLeafRoot(), and vacuumRedirectAndPlaceholder().

810 {
811  PageHeader phdr = (PageHeader) page;
812  Offset pd_lower = phdr->pd_lower;
813  Offset pd_upper = phdr->pd_upper;
814  Offset pd_special = phdr->pd_special;
816  ItemIdData newitemids[MaxIndexTuplesPerPage];
817  itemIdSort itemidptr;
818  ItemId lp;
819  int nline,
820  nused;
821  Size totallen;
822  Size size;
823  unsigned offset;
824  int nextitm;
825  OffsetNumber offnum;
826 
827  Assert(nitems <= MaxIndexTuplesPerPage);
828 
829  /*
830  * If there aren't very many items to delete, then retail
831  * PageIndexTupleDelete is the best way. Delete the items in reverse
832  * order so we don't have to think about adjusting item numbers for
833  * previous deletions.
834  *
835  * TODO: tune the magic number here
836  */
837  if (nitems <= 2)
838  {
839  while (--nitems >= 0)
840  PageIndexTupleDelete(page, itemnos[nitems]);
841  return;
842  }
843 
844  /*
845  * As with PageRepairFragmentation, paranoia seems justified.
846  */
847  if (pd_lower < SizeOfPageHeaderData ||
848  pd_lower > pd_upper ||
849  pd_upper > pd_special ||
850  pd_special > BLCKSZ ||
851  pd_special != MAXALIGN(pd_special))
852  ereport(ERROR,
853  (errcode(ERRCODE_DATA_CORRUPTED),
854  errmsg("corrupted page pointers: lower = %u, upper = %u, special = %u",
855  pd_lower, pd_upper, pd_special)));
856 
857  /*
858  * Scan the item pointer array and build a list of just the ones we are
859  * going to keep. Notice we do not modify the page yet, since we are
860  * still validity-checking.
861  */
862  nline = PageGetMaxOffsetNumber(page);
863  itemidptr = itemidbase;
864  totallen = 0;
865  nused = 0;
866  nextitm = 0;
867  for (offnum = FirstOffsetNumber; offnum <= nline; offnum = OffsetNumberNext(offnum))
868  {
869  lp = PageGetItemId(page, offnum);
871  size = ItemIdGetLength(lp);
872  offset = ItemIdGetOffset(lp);
873  if (offset < pd_upper ||
874  (offset + size) > pd_special ||
875  offset != MAXALIGN(offset))
876  ereport(ERROR,
877  (errcode(ERRCODE_DATA_CORRUPTED),
878  errmsg("corrupted item pointer: offset = %u, size = %u",
879  offset, (unsigned int) size)));
880 
881  if (nextitm < nitems && offnum == itemnos[nextitm])
882  {
883  /* skip item to be deleted */
884  nextitm++;
885  }
886  else
887  {
888  itemidptr->offsetindex = nused; /* where it will go */
889  itemidptr->itemoff = offset;
890  itemidptr->alignedlen = MAXALIGN(size);
891  totallen += itemidptr->alignedlen;
892  newitemids[nused] = *lp;
893  itemidptr++;
894  nused++;
895  }
896  }
897 
898  /* this will catch invalid or out-of-order itemnos[] */
899  if (nextitm != nitems)
900  elog(ERROR, "incorrect index offsets supplied");
901 
902  if (totallen > (Size) (pd_special - pd_lower))
903  ereport(ERROR,
904  (errcode(ERRCODE_DATA_CORRUPTED),
905  errmsg("corrupted item lengths: total %u, available space %u",
906  (unsigned int) totallen, pd_special - pd_lower)));
907 
908  /*
909  * Looks good. Overwrite the line pointers with the copy, from which we've
910  * removed all the unused items.
911  */
912  memcpy(phdr->pd_linp, newitemids, nused * sizeof(ItemIdData));
913  phdr->pd_lower = SizeOfPageHeaderData + nused * sizeof(ItemIdData);
914 
915  /* and compactify the tuple data */
916  compactify_tuples(itemidbase, nused, page);
917 }
int16 itemoff
Definition: bufpage.c:423
void PageIndexTupleDelete(Page page, OffsetNumber offnum)
Definition: bufpage.c:700
int errcode(int sqlerrcode)
Definition: elog.c:575
#define SizeOfPageHeaderData
Definition: bufpage.h:213
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:354
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:232
#define ItemIdHasStorage(itemId)
Definition: itemid.h:119
PageHeaderData * PageHeader
Definition: bufpage.h:162
#define Assert(condition)
Definition: c.h:671
signed int Offset
Definition: c.h:372
#define OffsetNumberNext(offsetNumber)
Definition: off.h:53
size_t Size
Definition: c.h:353
#define MAXALIGN(LEN)
Definition: c.h:584
#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
void PageIndexTupleDelete ( Page  page,
OffsetNumber  offnum 
)

Definition at line 700 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().

701 {
702  PageHeader phdr = (PageHeader) page;
703  char *addr;
704  ItemId tup;
705  Size size;
706  unsigned offset;
707  int nbytes;
708  int offidx;
709  int nline;
710 
711  /*
712  * As with PageRepairFragmentation, paranoia seems justified.
713  */
714  if (phdr->pd_lower < SizeOfPageHeaderData ||
715  phdr->pd_lower > phdr->pd_upper ||
716  phdr->pd_upper > phdr->pd_special ||
717  phdr->pd_special > BLCKSZ ||
718  phdr->pd_special != MAXALIGN(phdr->pd_special))
719  ereport(ERROR,
720  (errcode(ERRCODE_DATA_CORRUPTED),
721  errmsg("corrupted page pointers: lower = %u, upper = %u, special = %u",
722  phdr->pd_lower, phdr->pd_upper, phdr->pd_special)));
723 
724  nline = PageGetMaxOffsetNumber(page);
725  if ((int) offnum <= 0 || (int) offnum > nline)
726  elog(ERROR, "invalid index offnum: %u", offnum);
727 
728  /* change offset number to offset index */
729  offidx = offnum - 1;
730 
731  tup = PageGetItemId(page, offnum);
732  Assert(ItemIdHasStorage(tup));
733  size = ItemIdGetLength(tup);
734  offset = ItemIdGetOffset(tup);
735 
736  if (offset < phdr->pd_upper || (offset + size) > phdr->pd_special ||
737  offset != MAXALIGN(offset))
738  ereport(ERROR,
739  (errcode(ERRCODE_DATA_CORRUPTED),
740  errmsg("corrupted item pointer: offset = %u, size = %u",
741  offset, (unsigned int) size)));
742 
743  /* Amount of space to actually be deleted */
744  size = MAXALIGN(size);
745 
746  /*
747  * First, we want to get rid of the pd_linp entry for the index tuple. We
748  * copy all subsequent linp's back one slot in the array. We don't use
749  * PageGetItemId, because we are manipulating the _array_, not individual
750  * linp's.
751  */
752  nbytes = phdr->pd_lower -
753  ((char *) &phdr->pd_linp[offidx + 1] - (char *) phdr);
754 
755  if (nbytes > 0)
756  memmove((char *) &(phdr->pd_linp[offidx]),
757  (char *) &(phdr->pd_linp[offidx + 1]),
758  nbytes);
759 
760  /*
761  * Now move everything between the old upper bound (beginning of tuple
762  * space) and the beginning of the deleted tuple forward, so that space in
763  * the middle of the page is left free. If we've just deleted the tuple
764  * at the beginning of tuple space, then there's no need to do the copy.
765  */
766 
767  /* beginning of tuple space */
768  addr = (char *) page + phdr->pd_upper;
769 
770  if (offset > phdr->pd_upper)
771  memmove(addr + size, addr, offset - phdr->pd_upper);
772 
773  /* adjust free space boundary pointers */
774  phdr->pd_upper += size;
775  phdr->pd_lower -= sizeof(ItemIdData);
776 
777  /*
778  * Finally, we need to adjust the linp entries that remain.
779  *
780  * Anything that used to be before the deleted tuple's data was moved
781  * forward by the size of the deleted tuple.
782  */
783  if (!PageIsEmpty(page))
784  {
785  int i;
786 
787  nline--; /* there's one less than when we started */
788  for (i = 1; i <= nline; i++)
789  {
790  ItemId ii = PageGetItemId(phdr, i);
791 
793  if (ItemIdGetOffset(ii) <= offset)
794  ii->lp_off += size;
795  }
796  }
797 }
#define PageIsEmpty(page)
Definition: bufpage.h:219
int errcode(int sqlerrcode)
Definition: elog.c:575
#define SizeOfPageHeaderData
Definition: bufpage.h:213
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:354
#define ItemIdGetLength(itemId)
Definition: itemid.h:58
#define ERROR
Definition: elog.h:43
#define memmove(d, s, c)
Definition: c.h:1058
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:232
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:671
size_t Size
Definition: c.h:353
#define MAXALIGN(LEN)
Definition: c.h:584
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
void PageIndexTupleDeleteNoCompact ( Page  page,
OffsetNumber  offnum 
)

Definition at line 931 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(), and brin_xlog_update().

932 {
933  PageHeader phdr = (PageHeader) page;
934  char *addr;
935  ItemId tup;
936  Size size;
937  unsigned offset;
938  int nline;
939 
940  /*
941  * As with PageRepairFragmentation, paranoia seems justified.
942  */
943  if (phdr->pd_lower < SizeOfPageHeaderData ||
944  phdr->pd_lower > phdr->pd_upper ||
945  phdr->pd_upper > phdr->pd_special ||
946  phdr->pd_special > BLCKSZ ||
947  phdr->pd_special != MAXALIGN(phdr->pd_special))
948  ereport(ERROR,
949  (errcode(ERRCODE_DATA_CORRUPTED),
950  errmsg("corrupted page pointers: lower = %u, upper = %u, special = %u",
951  phdr->pd_lower, phdr->pd_upper, phdr->pd_special)));
952 
953  nline = PageGetMaxOffsetNumber(page);
954  if ((int) offnum <= 0 || (int) offnum > nline)
955  elog(ERROR, "invalid index offnum: %u", offnum);
956 
957  tup = PageGetItemId(page, offnum);
958  Assert(ItemIdHasStorage(tup));
959  size = ItemIdGetLength(tup);
960  offset = ItemIdGetOffset(tup);
961 
962  if (offset < phdr->pd_upper || (offset + size) > phdr->pd_special ||
963  offset != MAXALIGN(offset))
964  ereport(ERROR,
965  (errcode(ERRCODE_DATA_CORRUPTED),
966  errmsg("corrupted item pointer: offset = %u, size = %u",
967  offset, (unsigned int) size)));
968 
969  /* Amount of space to actually be deleted */
970  size = MAXALIGN(size);
971 
972  /*
973  * Either set the item pointer to "unused", or zap it if it's the last
974  * one. (Note: it's possible that the next-to-last one(s) are already
975  * unused, but we do not trouble to try to compact them out if so.)
976  */
977  if ((int) offnum < nline)
978  ItemIdSetUnused(tup);
979  else
980  {
981  phdr->pd_lower -= sizeof(ItemIdData);
982  nline--; /* there's one less than when we started */
983  }
984 
985  /*
986  * Now move everything between the old upper bound (beginning of tuple
987  * space) and the beginning of the deleted tuple forward, so that space in
988  * the middle of the page is left free. If we've just deleted the tuple
989  * at the beginning of tuple space, then there's no need to do the copy.
990  */
991 
992  /* beginning of tuple space */
993  addr = (char *) page + phdr->pd_upper;
994 
995  if (offset > phdr->pd_upper)
996  memmove(addr + size, addr, offset - phdr->pd_upper);
997 
998  /* adjust free space boundary pointer */
999  phdr->pd_upper += size;
1000 
1001  /*
1002  * Finally, we need to adjust the linp entries that remain.
1003  *
1004  * Anything that used to be before the deleted tuple's data was moved
1005  * forward by the size of the deleted tuple.
1006  */
1007  if (!PageIsEmpty(page))
1008  {
1009  int i;
1010 
1011  for (i = 1; i <= nline; i++)
1012  {
1013  ItemId ii = PageGetItemId(phdr, i);
1014 
1015  if (ItemIdHasStorage(ii) && ItemIdGetOffset(ii) <= offset)
1016  ii->lp_off += size;
1017  }
1018  }
1019 }
#define PageIsEmpty(page)
Definition: bufpage.h:219
int errcode(int sqlerrcode)
Definition: elog.c:575
#define SizeOfPageHeaderData
Definition: bufpage.h:213
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:354
#define ItemIdGetLength(itemId)
Definition: itemid.h:58
#define ERROR
Definition: elog.h:43
#define memmove(d, s, c)
Definition: c.h:1058
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:232
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:671
size_t Size
Definition: c.h:353
#define MAXALIGN(LEN)
Definition: c.h:584
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
bool PageIndexTupleOverwrite ( Page  page,
OffsetNumber  offnum,
Item  newtup,
Size  newsize 
)

Definition at line 1039 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().

1041 {
1042  PageHeader phdr = (PageHeader) page;
1043  ItemId tupid;
1044  int oldsize;
1045  unsigned offset;
1046  Size alignednewsize;
1047  int size_diff;
1048  int itemcount;
1049 
1050  /*
1051  * As with PageRepairFragmentation, paranoia seems justified.
1052  */
1053  if (phdr->pd_lower < SizeOfPageHeaderData ||
1054  phdr->pd_lower > phdr->pd_upper ||
1055  phdr->pd_upper > phdr->pd_special ||
1056  phdr->pd_special > BLCKSZ ||
1057  phdr->pd_special != MAXALIGN(phdr->pd_special))
1058  ereport(ERROR,
1059  (errcode(ERRCODE_DATA_CORRUPTED),
1060  errmsg("corrupted page pointers: lower = %u, upper = %u, special = %u",
1061  phdr->pd_lower, phdr->pd_upper, phdr->pd_special)));
1062 
1063  itemcount = PageGetMaxOffsetNumber(page);
1064  if ((int) offnum <= 0 || (int) offnum > itemcount)
1065  elog(ERROR, "invalid index offnum: %u", offnum);
1066 
1067  tupid = PageGetItemId(page, offnum);
1068  Assert(ItemIdHasStorage(tupid));
1069  oldsize = ItemIdGetLength(tupid);
1070  offset = ItemIdGetOffset(tupid);
1071 
1072  if (offset < phdr->pd_upper || (offset + oldsize) > phdr->pd_special ||
1073  offset != MAXALIGN(offset))
1074  ereport(ERROR,
1075  (errcode(ERRCODE_DATA_CORRUPTED),
1076  errmsg("corrupted item pointer: offset = %u, size = %u",
1077  offset, (unsigned int) oldsize)));
1078 
1079  /*
1080  * Determine actual change in space requirement, check for page overflow.
1081  */
1082  oldsize = MAXALIGN(oldsize);
1083  alignednewsize = MAXALIGN(newsize);
1084  if (alignednewsize > oldsize + (phdr->pd_upper - phdr->pd_lower))
1085  return false;
1086 
1087  /*
1088  * Relocate existing data and update line pointers, unless the new tuple
1089  * is the same size as the old (after alignment), in which case there's
1090  * nothing to do. Notice that what we have to relocate is data before the
1091  * target tuple, not data after, so it's convenient to express size_diff
1092  * as the amount by which the tuple's size is decreasing, making it the
1093  * delta to add to pd_upper and affected line pointers.
1094  */
1095  size_diff = oldsize - (int) alignednewsize;
1096  if (size_diff != 0)
1097  {
1098  char *addr = (char *) page + phdr->pd_upper;
1099  int i;
1100 
1101  /* relocate all tuple data before the target tuple */
1102  memmove(addr + size_diff, addr, offset - phdr->pd_upper);
1103 
1104  /* adjust free space boundary pointer */
1105  phdr->pd_upper += size_diff;
1106 
1107  /* adjust affected line pointers too */
1108  for (i = FirstOffsetNumber; i <= itemcount; i++)
1109  {
1110  ItemId ii = PageGetItemId(phdr, i);
1111 
1112  /* Allow items without storage; currently only BRIN needs that */
1113  if (ItemIdHasStorage(ii) && ItemIdGetOffset(ii) <= offset)
1114  ii->lp_off += size_diff;
1115  }
1116  }
1117 
1118  /* Update the item's tuple length (other fields shouldn't change) */
1119  ItemIdSetNormal(tupid, offset + size_diff, newsize);
1120 
1121  /* Copy new tuple data onto page */
1122  memcpy(PageGetItem(page, tupid), newtup, newsize);
1123 
1124  return true;
1125 }
int errcode(int sqlerrcode)
Definition: elog.c:575
#define SizeOfPageHeaderData
Definition: bufpage.h:213
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:354
#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:1058
#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:232
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:671
size_t Size
Definition: c.h:353
#define MAXALIGN(LEN)
Definition: c.h:584
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:337
LocationIndex pd_lower
Definition: bufpage.h:154
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:282
#define MemSet(start, val, len)
Definition: c.h:853
#define SizeOfPageHeaderData
Definition: bufpage.h:213
#define PG_PAGE_LAYOUT_VERSION
Definition: bufpage.h:196
LocationIndex pd_special
Definition: bufpage.h:156
PageHeaderData * PageHeader
Definition: bufpage.h:162
#define Assert(condition)
Definition: c.h:671
#define MAXALIGN(LEN)
Definition: c.h:584
LocationIndex pd_upper
Definition: bufpage.h:155
LocationIndex pd_lower
Definition: bufpage.h:154
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:4671
uint16 pd_checksum
Definition: bufpage.h:152
#define StaticAssertStmt(condition, errmessage)
Definition: c.h:753
unsigned short uint16
Definition: c.h:264
#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:182
#define MAXALIGN(LEN)
Definition: c.h:584
bool ignore_checksum_failure
Definition: bufpage.c:26
#define PageIsNew(page)
Definition: bufpage.h:226
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
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, and SizeOfPageHeaderData.

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

Definition at line 1143 of file bufpage.c.

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

Referenced by FlushBuffer().

1144 {
1145  static char *pageCopy = NULL;
1146 
1147  /* If we don't need a checksum, just return the passed-in data */
1148  if (PageIsNew(page) || !DataChecksumsEnabled())
1149  return (char *) page;
1150 
1151  /*
1152  * We allocate the copy space once and use it over on each subsequent
1153  * call. The point of palloc'ing here, rather than having a static char
1154  * array, is first to ensure adequate alignment for the checksumming code
1155  * and second to avoid wasting space in processes that never call this.
1156  */
1157  if (pageCopy == NULL)
1158  pageCopy = MemoryContextAlloc(TopMemoryContext, BLCKSZ);
1159 
1160  memcpy(pageCopy, (char *) page, BLCKSZ);
1161  ((PageHeader) pageCopy)->pd_checksum = pg_checksum_page(pageCopy, blkno);
1162  return pageCopy;
1163 }
bool DataChecksumsEnabled(void)
Definition: xlog.c:4671
MemoryContext TopMemoryContext
Definition: mcxt.c:43
PageHeaderData * PageHeader
Definition: bufpage.h:162
#define NULL
Definition: c.h:226
#define PageIsNew(page)
Definition: bufpage.h:226
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:749
uint16 pg_checksum_page(char *page, BlockNumber blkno)
void PageSetChecksumInplace ( Page  page,
BlockNumber  blkno 
)

Definition at line 1172 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().

1173 {
1174  /* If we don't need a checksum, just return */
1175  if (PageIsNew(page) || !DataChecksumsEnabled())
1176  return;
1177 
1178  ((PageHeader) page)->pd_checksum = pg_checksum_page((char *) page, blkno);
1179 }
bool DataChecksumsEnabled(void)
Definition: xlog.c:4671
PageHeaderData * PageHeader
Definition: bufpage.h:162
#define PageIsNew(page)
Definition: bufpage.h:226
uint16 pg_checksum_page(char *page, BlockNumber blkno)

Variable Documentation

bool ignore_checksum_failure = false

Definition at line 26 of file bufpage.c.

Referenced by PageIsVerified().