summaryrefslogtreecommitdiff
path: root/src/backend/storage/page/bufpage.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/storage/page/bufpage.c')
-rw-r--r--src/backend/storage/page/bufpage.c497
1 files changed, 0 insertions, 497 deletions
diff --git a/src/backend/storage/page/bufpage.c b/src/backend/storage/page/bufpage.c
deleted file mode 100644
index bffd403af21..00000000000
--- a/src/backend/storage/page/bufpage.c
+++ /dev/null
@@ -1,497 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * bufpage.c
- * POSTGRES standard buffer page code.
- *
- * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/storage/page/bufpage.c,v 1.45 2002/06/20 20:29:35 momjian Exp $
- *
- *-------------------------------------------------------------------------
- */
-#include "postgres.h"
-
-#include <sys/types.h>
-#include <sys/file.h>
-
-#include "storage/bufpage.h"
-
-
-/* ----------------------------------------------------------------
- * Page support functions
- * ----------------------------------------------------------------
- */
-
-/*
- * PageInit
- * Initializes the contents of a page.
- */
-void
-PageInit(Page page, Size pageSize, Size specialSize)
-{
- PageHeader p = (PageHeader) page;
-
- specialSize = MAXALIGN(specialSize);
-
- Assert(pageSize == BLCKSZ);
- Assert(pageSize >
- specialSize + sizeof(PageHeaderData) - sizeof(ItemIdData));
-
- /* Make sure all fields of page are zero, as well as unused space */
- MemSet(p, 0, pageSize);
-
- p->pd_lower = sizeof(PageHeaderData) - sizeof(ItemIdData);
- p->pd_upper = pageSize - specialSize;
- p->pd_special = pageSize - specialSize;
- PageSetPageSize(page, pageSize);
-}
-
-
-/* ----------------
- * PageAddItem
- *
- * Add an item to a page. Return value is offset at which it was
- * inserted, or InvalidOffsetNumber if there's not room to insert.
- *
- * If offsetNumber is valid and <= current max offset in the page,
- * insert item into the array at that position by shuffling ItemId's
- * down to make room.
- * If offsetNumber is not valid, then assign one by finding the first
- * one that is both unused and deallocated.
- *
- * !!! ELOG(ERROR) IS DISALLOWED HERE !!!
- *
- * ----------------
- */
-OffsetNumber
-PageAddItem(Page page,
- Item item,
- Size size,
- OffsetNumber offsetNumber,
- ItemIdFlags flags)
-{
- PageHeader phdr = (PageHeader) page;
- int i;
- Size alignedSize;
- int lower;
- int upper;
- ItemId itemId;
- OffsetNumber limit;
- bool needshuffle = false;
- bool overwritemode = (flags & OverwritePageMode) != 0;
-
- flags &= ~OverwritePageMode;
-
- /*
- * Be wary about corrupted page pointers
- */
- if (phdr->pd_lower < (sizeof(PageHeaderData) - sizeof(ItemIdData)) ||
- phdr->pd_lower > phdr->pd_upper ||
- phdr->pd_upper > phdr->pd_special ||
- phdr->pd_special > BLCKSZ)
- elog(ERROR, "PageAddItem: corrupted page pointers: lower = %u, upper = %u, special = %u",
- phdr->pd_lower, phdr->pd_upper, phdr->pd_special);
-
- /*
- * Find first unallocated offsetNumber
- */
- limit = OffsetNumberNext(PageGetMaxOffsetNumber(page));
-
- /* was offsetNumber passed in? */
- if (OffsetNumberIsValid(offsetNumber))
- {
- if (overwritemode)
- {
- if (offsetNumber > limit)
- {
- elog(WARNING, "PageAddItem: tried overwrite after maxoff");
- return InvalidOffsetNumber;
- }
- if (offsetNumber < limit)
- {
- itemId = &phdr->pd_linp[offsetNumber - 1];
- if (((*itemId).lp_flags & LP_USED) ||
- ((*itemId).lp_len != 0))
- {
- elog(WARNING, "PageAddItem: tried overwrite of used ItemId");
- return InvalidOffsetNumber;
- }
- }
- }
- else
- {
- /*
- * Don't actually do the shuffle till we've checked free
- * space!
- */
- needshuffle = true; /* need to increase "lower" */
- }
- }
- else
- {
- /* offsetNumber was not passed in, so find one */
- /* look for "recyclable" (unused & deallocated) ItemId */
- for (offsetNumber = 1; offsetNumber < limit; offsetNumber++)
- {
- itemId = &phdr->pd_linp[offsetNumber - 1];
- if ((((*itemId).lp_flags & LP_USED) == 0) &&
- ((*itemId).lp_len == 0))
- break;
- }
- }
-
- /*
- * 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)
- lower = (char *) (&phdr->pd_linp[offsetNumber]) - (char *) page;
- else 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.
- */
- if (needshuffle)
- {
- /* shuffle ItemId's (Do the PageManager Shuffle...) */
- for (i = (int) limit - 1; i >= (int) offsetNumber; i--)
- {
- ItemId fromitemId,
- toitemId;
-
- fromitemId = &phdr->pd_linp[i - 1];
- toitemId = &phdr->pd_linp[i];
- *toitemId = *fromitemId;
- }
- }
-
- itemId = &phdr->pd_linp[offsetNumber - 1];
- (*itemId).lp_off = upper;
- (*itemId).lp_len = size;
- (*itemId).lp_flags = flags;
-
- memmove((char *) page + upper, item, size);
-
- phdr->pd_lower = (LocationIndex) lower;
- phdr->pd_upper = (LocationIndex) upper;
-
- return offsetNumber;
-}
-
-/*
- * PageGetTempPage
- * Get a temporary page in local memory for special processing
- */
-Page
-PageGetTempPage(Page page, Size specialSize)
-{
- Size pageSize;
- Size size;
- Page temp;
- PageHeader thdr;
-
- pageSize = PageGetPageSize(page);
- temp = (Page) palloc(pageSize);
- thdr = (PageHeader) temp;
-
- /* copy old page in */
- memcpy(temp, page, pageSize);
-
- /* clear out the middle */
- size = (pageSize - sizeof(PageHeaderData)) + sizeof(ItemIdData);
- size -= MAXALIGN(specialSize);
- MemSet((char *) &(thdr->pd_linp[0]), 0, size);
-
- /* set high, low water marks */
- thdr->pd_lower = sizeof(PageHeaderData) - sizeof(ItemIdData);
- thdr->pd_upper = pageSize - MAXALIGN(specialSize);
-
- return temp;
-}
-
-/*
- * PageRestoreTempPage
- * Copy temporary page back to permanent page after special processing
- * and release the temporary page.
- */
-void
-PageRestoreTempPage(Page tempPage, Page oldPage)
-{
- Size pageSize;
-
- pageSize = PageGetPageSize(tempPage);
- memmove((char *) oldPage, (char *) tempPage, pageSize);
-
- pfree(tempPage);
-}
-
-/*
- * sorting support for PageRepairFragmentation
- */
-struct itemIdSortData
-{
- int offsetindex; /* linp array index */
- int itemoff; /* page offset of item data */
- Size alignedlen; /* MAXALIGN(item data len) */
-};
-
-static int
-itemoffcompare(const void *itemidp1, const void *itemidp2)
-{
- /* Sort in decreasing itemoff order */
- return ((struct itemIdSortData *) itemidp2)->itemoff -
- ((struct itemIdSortData *) itemidp1)->itemoff;
-}
-
-/*
- * PageRepairFragmentation
- *
- * Frees fragmented space on a page.
- * It doesn't remove unused line pointers! Please don't change this.
- * This routine is usable for heap pages only.
- *
- * Returns number of unused line pointers on page. If "unused" is not NULL
- * then the unused[] array is filled with indexes of unused line pointers.
- */
-int
-PageRepairFragmentation(Page page, OffsetNumber *unused)
-{
- Offset pd_lower = ((PageHeader) page)->pd_lower;
- Offset pd_upper = ((PageHeader) page)->pd_upper;
- Offset pd_special = ((PageHeader) page)->pd_special;
- struct itemIdSortData *itemidbase,
- *itemidptr;
- ItemId lp;
- int nline,
- nused;
- 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 < (sizeof(PageHeaderData) - sizeof(ItemIdData)) ||
- pd_lower > pd_upper ||
- pd_upper > pd_special ||
- pd_special > BLCKSZ ||
- pd_special != MAXALIGN(pd_special))
- elog(ERROR, "PageRepairFragmentation: corrupted page pointers: lower = %u, upper = %u, special = %u",
- pd_lower, pd_upper, pd_special);
-
- nline = PageGetMaxOffsetNumber(page);
- nused = 0;
- for (i = 0; i < nline; i++)
- {
- lp = ((PageHeader) page)->pd_linp + i;
- if ((*lp).lp_flags & LP_DELETE) /* marked for deletion */
- (*lp).lp_flags &= ~(LP_USED | LP_DELETE);
- if ((*lp).lp_flags & LP_USED)
- nused++;
- else if (unused)
- unused[i - nused] = (OffsetNumber) i;
- }
-
- if (nused == 0)
- {
- /* Page is completely empty, so just reset it quickly */
- for (i = 0; i < nline; i++)
- {
- lp = ((PageHeader) page)->pd_linp + i;
- (*lp).lp_len = 0; /* indicate unused & deallocated */
- }
- ((PageHeader) page)->pd_upper = pd_special;
- }
- else
- { /* nused != 0 */
- /* Need to compact the page the hard way */
- itemidbase = (struct itemIdSortData *)
- palloc(sizeof(struct itemIdSortData) * nused);
- itemidptr = itemidbase;
- totallen = 0;
- for (i = 0; i < nline; i++)
- {
- lp = ((PageHeader) page)->pd_linp + i;
- if ((*lp).lp_flags & LP_USED)
- {
- itemidptr->offsetindex = i;
- itemidptr->itemoff = (*lp).lp_off;
- if (itemidptr->itemoff < (int) pd_upper ||
- itemidptr->itemoff >= (int) pd_special)
- elog(ERROR, "PageRepairFragmentation: corrupted item pointer %u",
- itemidptr->itemoff);
- itemidptr->alignedlen = MAXALIGN((*lp).lp_len);
- totallen += itemidptr->alignedlen;
- itemidptr++;
- }
- else
- {
- (*lp).lp_len = 0; /* indicate unused & deallocated */
- }
- }
-
- if (totallen > (Size) (pd_special - pd_lower))
- elog(ERROR, "PageRepairFragmentation: corrupted item lengths, total %u, avail %u",
- (unsigned int) totallen, pd_special - pd_lower);
-
- /* sort itemIdSortData array into decreasing itemoff order */
- qsort((char *) itemidbase, nused, sizeof(struct itemIdSortData),
- itemoffcompare);
-
- /* compactify page */
- upper = pd_special;
-
- for (i = 0, itemidptr = itemidbase; i < nused; i++, itemidptr++)
- {
- lp = ((PageHeader) page)->pd_linp + itemidptr->offsetindex;
- upper -= itemidptr->alignedlen;
- memmove((char *) page + upper,
- (char *) page + itemidptr->itemoff,
- itemidptr->alignedlen);
- (*lp).lp_off = upper;
- }
-
- ((PageHeader) page)->pd_upper = upper;
-
- pfree(itemidbase);
- }
-
- return (nline - nused);
-}
-
-/*
- * PageGetFreeSpace
- * Returns the size of the free (allocatable) space on a page.
- */
-Size
-PageGetFreeSpace(Page page)
-{
- 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); /* XXX not always appropriate */
-
- return (Size) space;
-}
-
-
-/*
- * PageIndexTupleDelete
- *
- * This routine does the work of removing a tuple from an index page.
- *
- * Unlike heap pages, we compact out the line pointer for the removed tuple.
- */
-void
-PageIndexTupleDelete(Page page, OffsetNumber offnum)
-{
- PageHeader phdr = (PageHeader) page;
- char *addr;
- ItemId tup;
- Size size;
- unsigned offset;
- int nbytes;
- int offidx;
- int nline,
- i;
-
- /*
- * As with PageRepairFragmentation, paranoia seems justified.
- */
- if (phdr->pd_lower < (sizeof(PageHeaderData) - sizeof(ItemIdData)) ||
- phdr->pd_lower > phdr->pd_upper ||
- phdr->pd_upper > phdr->pd_special ||
- phdr->pd_special > BLCKSZ)
- elog(ERROR, "PageIndexTupleDelete: 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, "PageIndexTupleDelete: bad offnum %u", offnum);
-
- /* change offset number to offset index */
- offidx = offnum - 1;
-
- tup = PageGetItemId(page, offnum);
- size = ItemIdGetLength(tup);
- offset = ItemIdGetOffset(tup);
-
- if (offset < phdr->pd_upper || (offset + size) > phdr->pd_special ||
- offset != MAXALIGN(offset) || size != MAXALIGN(size))
- elog(ERROR, "PageIndexTupleDelete: 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.
- */
- nbytes = phdr->pd_lower -
- ((char *) &phdr->pd_linp[offidx + 1] - (char *) phdr);
-
- 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))
- {
- nline--; /* there's one less than when we started */
- for (i = nline; --i >= 0; )
- {
- if (phdr->pd_linp[i].lp_off <= offset)
- phdr->pd_linp[i].lp_off += size;
- }
- }
-}