#include "postgres.h"
#include "access/htup_details.h"
#include "access/xlog.h"
#include "storage/checksum.h"
Go to the source code of this file.
typedef itemIdSortData* itemIdSort |
typedef struct itemIdSortData itemIdSortData |
static int itemoffcompare | ( | const void * | itemidp1, | |
const void * | itemidp2 | |||
) | [static] |
Definition at line 399 of file bufpage.c.
Referenced by PageIndexMultiDelete(), and PageRepairFragmentation().
{ /* Sort in decreasing itemoff order */ return ((itemIdSort) itemidp2)->itemoff - ((itemIdSort) itemidp1)->itemoff; }
OffsetNumber PageAddItem | ( | Page | page, | |
Item | item, | |||
Size | size, | |||
OffsetNumber | offsetNumber, | |||
bool | overwrite, | |||
bool | is_heap | |||
) |
Definition at line 175 of file bufpage.c.
References elog, ereport, errcode(), errmsg(), ItemIdHasStorage, ItemIdIsUsed, ItemIdSetNormal, MAXALIGN, MaxHeapTuplesPerPage, memmove, OffsetNumberIsValid, OffsetNumberNext, PageClearHasFreeLinePointers, PageGetItemId, PageGetMaxOffsetNumber, PageHasFreeLinePointers, PANIC, PageHeaderData::pd_lower, PageHeaderData::pd_special, PageHeaderData::pd_upper, SizeOfPageHeaderData, and WARNING.
Referenced by _bt_newroot(), _bt_pgaddtup(), _bt_restore_page(), _bt_sortaddtup(), _bt_split(), _hash_pgaddtup(), addLeafTuple(), addOrReplaceTuple(), btree_xlog_insert(), btree_xlog_split(), doPickSplit(), entryPlaceToPage(), entrySplitPage(), ginEntryFillRoot(), ginHeapTupleFastInsert(), ginRedoInsert(), ginRedoInsertListPage(), ginRedoSplit(), ginRedoUpdateMetapage(), ginRedoVacuumPage(), ginVacuumEntryPage(), gistfillbuffer(), gistplacetopage(), gistRedoPageUpdateRecord(), heap_xlog_insert(), heap_xlog_multi_insert(), heap_xlog_update(), raw_heap_insert(), RelationPutHeapTuple(), seq_redo(), spgAddNodeAction(), SpGistPageAddNewItem(), spgPageIndexMultiDelete(), spgRedoAddLeaf(), spgRedoAddNode(), spgRedoSplitTuple(), spgSplitNodeAction(), and writeListPage().
{ PageHeader phdr = (PageHeader) page; Size alignedSize; int lower; int upper; ItemId itemId; OffsetNumber limit; bool needshuffle = false; /* * Be wary about corrupted page pointers */ if (phdr->pd_lower < SizeOfPageHeaderData || phdr->pd_lower > phdr->pd_upper || phdr->pd_upper > phdr->pd_special || phdr->pd_special > BLCKSZ) ereport(PANIC, (errcode(ERRCODE_DATA_CORRUPTED), errmsg("corrupted page pointers: lower = %u, upper = %u, special = %u", phdr->pd_lower, phdr->pd_upper, phdr->pd_special))); /* * Select offsetNumber to place the new item at */ limit = OffsetNumberNext(PageGetMaxOffsetNumber(page)); /* was offsetNumber passed in? */ if (OffsetNumberIsValid(offsetNumber)) { /* yes, check it */ if (overwrite) { if (offsetNumber < limit) { itemId = PageGetItemId(phdr, offsetNumber); if (ItemIdIsUsed(itemId) || ItemIdHasStorage(itemId)) { elog(WARNING, "will not overwrite a used ItemId"); return InvalidOffsetNumber; } } } else { if (offsetNumber < limit) needshuffle = true; /* need to move existing linp's */ } } else { /* offsetNumber was not passed in, so find a free slot */ /* if no free slot, we'll put it at limit (1st open slot) */ if (PageHasFreeLinePointers(phdr)) { /* * Look for "recyclable" (unused) ItemId. We check for no storage * as well, just to be paranoid --- unused items should never have * storage. */ for (offsetNumber = 1; offsetNumber < limit; offsetNumber++) { itemId = PageGetItemId(phdr, offsetNumber); if (!ItemIdIsUsed(itemId) && !ItemIdHasStorage(itemId)) break; } if (offsetNumber >= limit) { /* the hint is wrong, so reset it */ PageClearHasFreeLinePointers(phdr); } } else { /* don't bother searching if hint says there's no free slot */ offsetNumber = limit; } } if (offsetNumber > limit) { elog(WARNING, "specified item offset is too large"); return InvalidOffsetNumber; } if (is_heap && offsetNumber > MaxHeapTuplesPerPage) { elog(WARNING, "can't put more than MaxHeapTuplesPerPage items in a heap page"); return InvalidOffsetNumber; } /* * Compute new lower and upper pointers for page, see if it'll fit. * * Note: do arithmetic as signed ints, to avoid mistakes if, say, * alignedSize > pd_upper. */ if (offsetNumber == limit || needshuffle) lower = phdr->pd_lower + sizeof(ItemIdData); else lower = phdr->pd_lower; alignedSize = MAXALIGN(size); upper = (int) phdr->pd_upper - (int) alignedSize; if (lower > upper) return InvalidOffsetNumber; /* * OK to insert the item. First, shuffle the existing pointers if needed. */ itemId = PageGetItemId(phdr, offsetNumber); if (needshuffle) memmove(itemId + 1, itemId, (limit - offsetNumber) * sizeof(ItemIdData)); /* set the item pointer */ ItemIdSetNormal(itemId, upper, size); /* copy the item's data onto the page */ memcpy((char *) page + upper, item, size); /* adjust page header */ phdr->pd_lower = (LocationIndex) lower; phdr->pd_upper = (LocationIndex) upper; return offsetNumber; }
static uint16 PageCalcChecksum16 | ( | Page | page, | |
BlockNumber | blkno | |||
) | [static] |
Definition at line 950 of file bufpage.c.
References Assert, checksum_block(), PageIsNew, and PageHeaderData::pd_checksum.
Referenced by PageIsVerified(), and PageSetChecksumInplace().
{ PageHeader phdr = (PageHeader) page; uint16 save_checksum; uint32 checksum; /* only calculate the checksum for properly-initialized pages */ Assert(!PageIsNew(page)); /* * Save pd_checksum and set it to zero, so that the checksum calculation * isn't affected by the checksum stored on the page. We do this to * allow optimization of the checksum calculation on the whole block * in one go. */ save_checksum = phdr->pd_checksum; phdr->pd_checksum = 0; checksum = checksum_block(page, BLCKSZ); phdr->pd_checksum = save_checksum; /* mix in the block number to detect transposed pages */ checksum ^= blkno; /* * Reduce to a uint16 (to fit in the pd_checksum field) with an offset of * one. That avoids checksums of zero, which seems like a good idea. */ return (checksum % 65535) + 1; }
Definition at line 565 of file bufpage.c.
Referenced by _bt_findsplitloc(), allocNewBuffer(), doPickSplit(), ginHeapTupleFastInsert(), spgAddNodeAction(), SpGistGetBuffer(), SpGistPageAddNewItem(), SpGistSetLastUsedPage(), and writeListPage().
{ int space; /* * Use signed arithmetic here so that we behave sensibly if pd_lower > * pd_upper. */ space = (int) ((PageHeader) page)->pd_upper - (int) ((PageHeader) page)->pd_lower; if (space < 0) return 0; return (Size) space; }
Definition at line 541 of file bufpage.c.
Referenced by _bt_buildadd(), _bt_findinsertloc(), _bt_insertonpg(), _hash_doinsert(), _hash_splitbucket(), _hash_squeezebucket(), entryIsEnoughSpace(), GetBTPageStatistics(), gistnospace(), PageGetHeapFreeSpace(), pgstat_index_page(), and pgstatindex().
{ int space; /* * Use signed arithmetic here so that we behave sensibly if pd_lower > * pd_upper. */ space = (int) ((PageHeader) page)->pd_upper - (int) ((PageHeader) page)->pd_lower; if (space < (int) sizeof(ItemIdData)) return 0; space -= sizeof(ItemIdData); return (Size) space; }
Definition at line 598 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(), and RelationGetBufferForTuple().
{ Size space; space = PageGetFreeSpace(page); if (space > 0) { OffsetNumber offnum, nline; /* * Are there already MaxHeapTuplesPerPage line pointers in the page? */ nline = PageGetMaxOffsetNumber(page); if (nline >= MaxHeapTuplesPerPage) { if (PageHasFreeLinePointers((PageHeader) page)) { /* * Since this is just a hint, we must confirm that there is * indeed a free line pointer */ for (offnum = FirstOffsetNumber; offnum <= nline; offnum = OffsetNumberNext(offnum)) { ItemId lp = PageGetItemId(page, offnum); if (!ItemIdIsUsed(lp)) break; } if (offnum > nline) { /* * The hint is wrong, but we can't clear it here since we * don't have the ability to mark the page dirty. */ space = 0; } } else { /* * Although the hint might be wrong, PageAddItem will believe * it anyway, so we must believe it too. */ space = 0; } } } return space; }
Definition at line 317 of file bufpage.c.
References PageGetPageSize, and palloc().
Referenced by _bt_split().
{ Size pageSize; Page temp; pageSize = PageGetPageSize(page); temp = (Page) palloc(pageSize); return temp; }
Definition at line 334 of file bufpage.c.
References PageGetPageSize, and palloc().
Referenced by dataSplitPage(), entrySplitPage(), and ginVacuumEntryPage().
{ Size pageSize; Page temp; pageSize = PageGetPageSize(page); temp = (Page) palloc(pageSize); memcpy(temp, page, pageSize); return temp; }
Definition at line 354 of file bufpage.c.
References PageGetPageSize, PageGetSpecialPointer, PageGetSpecialSize, PageInit(), and palloc().
Referenced by gistplacetopage().
{ Size pageSize; Page temp; pageSize = PageGetPageSize(page); temp = (Page) palloc(pageSize); PageInit(temp, pageSize, PageGetSpecialSize(page)); memcpy(PageGetSpecialPointer(temp), PageGetSpecialPointer(page), PageGetSpecialSize(page)); return temp; }
void PageIndexMultiDelete | ( | Page | page, | |
OffsetNumber * | itemnos, | |||
int | nitems | |||
) |
Definition at line 765 of file bufpage.c.
References itemIdSortData::alignedlen, Assert, elog, ereport, errcode(), errmsg(), ERROR, FirstOffsetNumber, i, ItemIdGetLength, ItemIdGetOffset, ItemIdHasStorage, itemIdSortData::itemoff, itemoffcompare(), ItemIdData::lp_off, MAXALIGN, memmove, itemIdSortData::offsetindex, OffsetNumberNext, itemIdSortData::olditemid, PageGetItemId, PageGetMaxOffsetNumber, PageIndexTupleDelete(), palloc(), PageHeaderData::pd_lower, PageHeaderData::pd_special, PageHeaderData::pd_upper, pfree(), qsort, and SizeOfPageHeaderData.
Referenced by _bt_delitems_delete(), _bt_delitems_vacuum(), _hash_splitbucket(), _hash_squeezebucket(), btree_xlog_delete(), btree_xlog_split(), btree_xlog_vacuum(), ginRedoVacuumPage(), hashbulkdelete(), spgPageIndexMultiDelete(), spgRedoVacuumRedirect(), spgRedoVacuumRoot(), vacuumLeafRoot(), and vacuumRedirectAndPlaceholder().
{ PageHeader phdr = (PageHeader) page; Offset pd_lower = phdr->pd_lower; Offset pd_upper = phdr->pd_upper; Offset pd_special = phdr->pd_special; itemIdSort itemidbase, itemidptr; ItemId lp; int nline, nused; int i; Size totallen; Offset upper; Size size; unsigned offset; int nextitm; OffsetNumber offnum; /* * If there aren't very many items to delete, then retail * PageIndexTupleDelete is the best way. Delete the items in reverse * order so we don't have to think about adjusting item numbers for * previous deletions. * * TODO: tune the magic number here */ if (nitems <= 2) { while (--nitems >= 0) PageIndexTupleDelete(page, itemnos[nitems]); return; } /* * As with PageRepairFragmentation, paranoia seems justified. */ if (pd_lower < SizeOfPageHeaderData || pd_lower > pd_upper || pd_upper > pd_special || pd_special > BLCKSZ || pd_special != MAXALIGN(pd_special)) ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), errmsg("corrupted page pointers: lower = %u, upper = %u, special = %u", pd_lower, pd_upper, pd_special))); /* * Scan the item pointer array and build a list of just the ones we are * going to keep. Notice we do not modify the page yet, since we are * still validity-checking. */ nline = PageGetMaxOffsetNumber(page); itemidbase = (itemIdSort) palloc(sizeof(itemIdSortData) * nline); itemidptr = itemidbase; totallen = 0; nused = 0; nextitm = 0; for (offnum = FirstOffsetNumber; offnum <= nline; offnum = OffsetNumberNext(offnum)) { lp = PageGetItemId(page, offnum); Assert(ItemIdHasStorage(lp)); size = ItemIdGetLength(lp); offset = ItemIdGetOffset(lp); if (offset < pd_upper || (offset + size) > pd_special || offset != MAXALIGN(offset)) ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), errmsg("corrupted item pointer: offset = %u, size = %u", offset, (unsigned int) size))); if (nextitm < nitems && offnum == itemnos[nextitm]) { /* skip item to be deleted */ nextitm++; } else { itemidptr->offsetindex = nused; /* where it will go */ itemidptr->itemoff = offset; itemidptr->olditemid = *lp; itemidptr->alignedlen = MAXALIGN(size); totallen += itemidptr->alignedlen; itemidptr++; nused++; } } /* this will catch invalid or out-of-order itemnos[] */ if (nextitm != nitems) elog(ERROR, "incorrect index offsets supplied"); if (totallen > (Size) (pd_special - pd_lower)) ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), errmsg("corrupted item lengths: total %u, available space %u", (unsigned int) totallen, pd_special - pd_lower))); /* sort itemIdSortData array into decreasing itemoff order */ qsort((char *) itemidbase, nused, sizeof(itemIdSortData), itemoffcompare); /* compactify page and install new itemids */ upper = pd_special; for (i = 0, itemidptr = itemidbase; i < nused; i++, itemidptr++) { lp = PageGetItemId(page, itemidptr->offsetindex + 1); upper -= itemidptr->alignedlen; memmove((char *) page + upper, (char *) page + itemidptr->itemoff, itemidptr->alignedlen); *lp = itemidptr->olditemid; lp->lp_off = upper; } phdr->pd_lower = SizeOfPageHeaderData + nused * sizeof(ItemIdData); phdr->pd_upper = upper; pfree(itemidbase); }
void PageIndexTupleDelete | ( | Page | page, | |
OffsetNumber | offnum | |||
) |
Definition at line 659 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_pagedel(), addLeafTuple(), addOrReplaceTuple(), btree_xlog_delete_page(), entryPreparePage(), ginRedoInsert(), ginVacuumEntryPage(), gistbulkdelete(), gistplacetopage(), gistRedoPageUpdateRecord(), PageIndexMultiDelete(), spgAddNodeAction(), SpGistPageAddNewItem(), spgRedoAddLeaf(), spgRedoAddNode(), spgRedoSplitTuple(), and spgSplitNodeAction().
{ PageHeader phdr = (PageHeader) page; char *addr; ItemId tup; Size size; unsigned offset; int nbytes; int offidx; int nline; /* * As with PageRepairFragmentation, paranoia seems justified. */ if (phdr->pd_lower < SizeOfPageHeaderData || phdr->pd_lower > phdr->pd_upper || phdr->pd_upper > phdr->pd_special || phdr->pd_special > BLCKSZ) ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), errmsg("corrupted page pointers: lower = %u, upper = %u, special = %u", phdr->pd_lower, phdr->pd_upper, phdr->pd_special))); nline = PageGetMaxOffsetNumber(page); if ((int) offnum <= 0 || (int) offnum > nline) elog(ERROR, "invalid index offnum: %u", offnum); /* change offset number to offset index */ offidx = offnum - 1; tup = PageGetItemId(page, offnum); Assert(ItemIdHasStorage(tup)); size = ItemIdGetLength(tup); offset = ItemIdGetOffset(tup); if (offset < phdr->pd_upper || (offset + size) > phdr->pd_special || offset != MAXALIGN(offset) || size != MAXALIGN(size)) ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), errmsg("corrupted item pointer: offset = %u, size = %u", offset, (unsigned int) size))); /* * First, we want to get rid of the pd_linp entry for the index tuple. We * copy all subsequent linp's back one slot in the array. We don't use * PageGetItemId, because we are manipulating the _array_, not individual * linp's. */ nbytes = phdr->pd_lower - ((char *) &phdr->pd_linp[offidx + 1] - (char *) phdr); if (nbytes > 0) memmove((char *) &(phdr->pd_linp[offidx]), (char *) &(phdr->pd_linp[offidx + 1]), nbytes); /* * Now move everything between the old upper bound (beginning of tuple * space) and the beginning of the deleted tuple forward, so that space in * the middle of the page is left free. If we've just deleted the tuple * at the beginning of tuple space, then there's no need to do the copy * (and bcopy on some architectures SEGV's if asked to move zero bytes). */ /* beginning of tuple space */ addr = (char *) page + phdr->pd_upper; if (offset > phdr->pd_upper) memmove(addr + size, addr, (int) (offset - phdr->pd_upper)); /* adjust free space boundary pointers */ phdr->pd_upper += size; phdr->pd_lower -= sizeof(ItemIdData); /* * Finally, we need to adjust the linp entries that remain. * * Anything that used to be before the deleted tuple's data was moved * forward by the size of the deleted tuple. */ if (!PageIsEmpty(page)) { int i; nline--; /* there's one less than when we started */ for (i = 1; i <= nline; i++) { ItemId ii = PageGetItemId(phdr, i); Assert(ItemIdHasStorage(ii)); if (ItemIdGetOffset(ii) <= offset) ii->lp_off += size; } } }
Definition at line 40 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(), fill_seq_with_data(), fsm_extend(), fsm_readbuf(), GinInitPage(), GISTInitBuffer(), heap_xlog_insert(), heap_xlog_multi_insert(), heap_xlog_update(), lazy_scan_heap(), PageGetTempPageCopySpecial(), raw_heap_insert(), RelationGetBufferForTuple(), seq_redo(), SetMatViewToPopulated(), SpGistInitPage(), vm_extend(), vm_readbuf(), and XLogRecordPageWithFreeSpace().
{ PageHeader p = (PageHeader) page; specialSize = MAXALIGN(specialSize); Assert(pageSize == BLCKSZ); Assert(pageSize > specialSize + SizeOfPageHeaderData); /* Make sure all fields of page are zero, as well as unused space */ MemSet(p, 0, pageSize); p->pd_flags = 0; p->pd_lower = SizeOfPageHeaderData; p->pd_upper = pageSize - specialSize; p->pd_special = pageSize - specialSize; PageSetPageSizeAndVersion(page, pageSize, PG_PAGE_LAYOUT_VERSION); /* p->pd_prune_xid = InvalidTransactionId; done by above MemSet */ }
bool PageIsVerified | ( | Page | page, | |
BlockNumber | blkno | |||
) |
Definition at line 80 of file bufpage.c.
References DataChecksumsEnabled(), ereport, errmsg(), i, ignore_checksum_failure, MAXALIGN, PageCalcChecksum16(), PageIsNew, PageHeaderData::pd_checksum, PageHeaderData::pd_flags, PageHeaderData::pd_lower, PageHeaderData::pd_special, PageHeaderData::pd_upper, PD_VALID_FLAG_BITS, and WARNING.
Referenced by copy_relation_data(), and ReadBuffer_common().
{ PageHeader p = (PageHeader) page; char *pagebytes; int i; bool checksum_failure = false; bool header_sane = false; bool all_zeroes = false; uint16 checksum = 0; /* * Don't verify page data unless the page passes basic non-zero test */ if (!PageIsNew(page)) { if (DataChecksumsEnabled()) { checksum = PageCalcChecksum16(page, blkno); if (checksum != p->pd_checksum) checksum_failure = true; } /* * The following checks don't prove the header is correct, * only that it looks sane enough to allow into the buffer pool. * Later usage of the block can still reveal problems, * which is why we offer the checksum option. */ if ((p->pd_flags & ~PD_VALID_FLAG_BITS) == 0 && p->pd_lower <= p->pd_upper && p->pd_upper <= p->pd_special && p->pd_special <= BLCKSZ && p->pd_special == MAXALIGN(p->pd_special)) header_sane = true; if (header_sane && !checksum_failure) return true; } /* Check all-zeroes case */ all_zeroes = true; pagebytes = (char *) page; for (i = 0; i < BLCKSZ; i++) { if (pagebytes[i] != 0) { all_zeroes = false; break; } } if (all_zeroes) return true; /* * Throw a WARNING if the checksum fails, but only after we've checked for * the all-zeroes case. */ if (checksum_failure) { ereport(WARNING, (ERRCODE_DATA_CORRUPTED, errmsg("page verification failed, calculated checksum %u but expected %u", checksum, p->pd_checksum))); if (header_sane && ignore_checksum_failure) return true; } return false; }
void PageRepairFragmentation | ( | Page | page | ) |
Definition at line 417 of file bufpage.c.
References itemIdSortData::alignedlen, ereport, errcode(), errmsg(), ERROR, FirstOffsetNumber, i, ItemIdGetLength, ItemIdGetOffset, ItemIdHasStorage, ItemIdIsUsed, ItemIdSetUnused, itemIdSortData::itemoff, itemoffcompare(), ItemIdData::lp_off, MAXALIGN, memmove, itemIdSortData::offsetindex, PageClearHasFreeLinePointers, PageGetItemId, PageGetMaxOffsetNumber, PageSetHasFreeLinePointers, palloc(), pfree(), qsort, and SizeOfPageHeaderData.
Referenced by heap_page_prune_execute(), and lazy_vacuum_page().
{ Offset pd_lower = ((PageHeader) page)->pd_lower; Offset pd_upper = ((PageHeader) page)->pd_upper; Offset pd_special = ((PageHeader) page)->pd_special; itemIdSort itemidbase, itemidptr; ItemId lp; int nline, nstorage, nunused; int i; Size totallen; Offset upper; /* * It's worth the trouble to be more paranoid here than in most places, * because we are about to reshuffle data in (what is usually) a shared * disk buffer. If we aren't careful then corrupted pointers, lengths, * etc could cause us to clobber adjacent disk buffers, spreading the data * loss further. So, check everything. */ if (pd_lower < SizeOfPageHeaderData || pd_lower > pd_upper || pd_upper > pd_special || pd_special > BLCKSZ || pd_special != MAXALIGN(pd_special)) ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), errmsg("corrupted page pointers: lower = %u, upper = %u, special = %u", pd_lower, pd_upper, pd_special))); nline = PageGetMaxOffsetNumber(page); nunused = nstorage = 0; for (i = FirstOffsetNumber; i <= nline; i++) { lp = PageGetItemId(page, i); if (ItemIdIsUsed(lp)) { if (ItemIdHasStorage(lp)) nstorage++; } else { /* Unused entries should have lp_len = 0, but make sure */ ItemIdSetUnused(lp); nunused++; } } if (nstorage == 0) { /* Page is completely empty, so just reset it quickly */ ((PageHeader) page)->pd_upper = pd_special; } else { /* nstorage != 0 */ /* Need to compact the page the hard way */ itemidbase = (itemIdSort) palloc(sizeof(itemIdSortData) * nstorage); itemidptr = itemidbase; totallen = 0; for (i = 0; i < nline; i++) { lp = PageGetItemId(page, i + 1); if (ItemIdHasStorage(lp)) { itemidptr->offsetindex = i; itemidptr->itemoff = ItemIdGetOffset(lp); if (itemidptr->itemoff < (int) pd_upper || itemidptr->itemoff >= (int) pd_special) ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), errmsg("corrupted item pointer: %u", itemidptr->itemoff))); itemidptr->alignedlen = MAXALIGN(ItemIdGetLength(lp)); totallen += itemidptr->alignedlen; itemidptr++; } } if (totallen > (Size) (pd_special - pd_lower)) ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), errmsg("corrupted item lengths: total %u, available space %u", (unsigned int) totallen, pd_special - pd_lower))); /* sort itemIdSortData array into decreasing itemoff order */ qsort((char *) itemidbase, nstorage, sizeof(itemIdSortData), itemoffcompare); /* compactify page */ upper = pd_special; for (i = 0, itemidptr = itemidbase; i < nstorage; i++, itemidptr++) { lp = PageGetItemId(page, itemidptr->offsetindex + 1); upper -= itemidptr->alignedlen; memmove((char *) page + upper, (char *) page + itemidptr->itemoff, itemidptr->alignedlen); lp->lp_off = upper; } ((PageHeader) page)->pd_upper = upper; pfree(itemidbase); } /* Set hint bit for PageAddItem */ if (nunused > 0) PageSetHasFreeLinePointers(page); else PageClearHasFreeLinePointers(page); }
Definition at line 376 of file bufpage.c.
References PageGetPageSize, and pfree().
Referenced by _bt_split(), ginbulkdelete(), ginInsertValue(), and gistplacetopage().
{ Size pageSize; pageSize = PageGetPageSize(tempPage); memcpy((char *) oldPage, (char *) tempPage, pageSize); pfree(tempPage); }
char* PageSetChecksumCopy | ( | Page | page, | |
BlockNumber | blkno | |||
) |
Definition at line 901 of file bufpage.c.
References DataChecksumsEnabled(), pageCopy, PageIsNew, and PageSetChecksumInplace().
Referenced by FlushBuffer().
{ if (PageIsNew(page) || !DataChecksumsEnabled()) return (char *) page; /* * We make a copy iff we need to calculate a checksum because other * backends may set hint bits on this page while we write, which * would mean the checksum differs from the page contents. It doesn't * matter if we include or exclude hints during the copy, as long * as we write a valid page and associated checksum. */ memcpy((char *) pageCopy, (char *) page, BLCKSZ); PageSetChecksumInplace(pageCopy, blkno); return (char *) pageCopy; }
void PageSetChecksumInplace | ( | Page | page, | |
BlockNumber | blkno | |||
) |
Definition at line 926 of file bufpage.c.
References DataChecksumsEnabled(), PageCalcChecksum16(), PageIsNew, and PageHeaderData::pd_checksum.
Referenced by _bt_blwritepage(), btbuildempty(), copy_relation_data(), end_heap_rewrite(), FlushRelationBuffers(), fsm_extend(), LocalBufferAlloc(), PageSetChecksumCopy(), raw_heap_insert(), SetMatViewToPopulated(), spgbuildempty(), and vm_extend().
{ if (PageIsNew(page)) return; if (DataChecksumsEnabled()) { PageHeader p = (PageHeader) page; p->pd_checksum = PageCalcChecksum16(page, blkno); } return; }
bool ignore_checksum_failure = false |
Definition at line 21 of file bufpage.c.
Referenced by PageIsVerified().
Page pageCopy = pageCopyData [static] |
Definition at line 24 of file bufpage.c.
Referenced by PageSetChecksumCopy().
char pageCopyData[BLCKSZ] [static] |