1
0
mirror of https://github.com/postgres/postgres.git synced 2025-09-02 04:21:28 +03:00

Redefine the lp_flags field of item pointers as having four states, rather

than two independent bits (one of which was never used in heap pages anyway,
or at least hadn't been in a very long time).  This gives us flexibility to
add the HOT notions of redirected and dead item pointers without requiring
anything so klugy as magic values of lp_off and lp_len.  The state values
are chosen so that for the states currently in use (pre-HOT) there is no
change in the physical representation.
This commit is contained in:
Tom Lane
2007-09-12 22:10:26 +00:00
parent eb0a7735ba
commit 6889303531
31 changed files with 278 additions and 185 deletions

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/storage/page/bufpage.c,v 1.72 2007/03/02 00:48:44 tgl Exp $
* $PostgreSQL: pgsql/src/backend/storage/page/bufpage.c,v 1.73 2007/09/12 22:10:26 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -99,7 +99,10 @@ PageHeaderIsValid(PageHeader page)
* 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,
* If overwrite is true, we just store the item at the specified
* offsetNumber (which must be either a currently-unused item pointer,
* or one past the last existing item). Otherwise,
* 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
@@ -112,7 +115,7 @@ PageAddItem(Page page,
Item item,
Size size,
OffsetNumber offsetNumber,
ItemIdFlags flags)
bool overwrite)
{
PageHeader phdr = (PageHeader) page;
Size alignedSize;
@@ -121,9 +124,6 @@ PageAddItem(Page page,
ItemId itemId;
OffsetNumber limit;
bool needshuffle = false;
bool overwritemode = (flags & OverwritePageMode) != 0;
flags &= ~OverwritePageMode;
/*
* Be wary about corrupted page pointers
@@ -146,12 +146,12 @@ PageAddItem(Page page,
if (OffsetNumberIsValid(offsetNumber))
{
/* yes, check it */
if (overwritemode)
if (overwrite)
{
if (offsetNumber < limit)
{
itemId = PageGetItemId(phdr, offsetNumber);
if (ItemIdIsUsed(itemId) || ItemIdGetLength(itemId) != 0)
if (ItemIdIsUsed(itemId) || ItemIdHasStorage(itemId))
{
elog(WARNING, "will not overwrite a used ItemId");
return InvalidOffsetNumber;
@@ -170,11 +170,15 @@ PageAddItem(Page page,
/* if no free slot, we'll put it at limit (1st open slot) */
if (PageHasFreeLinePointers(phdr))
{
/* look for "recyclable" (unused & deallocated) ItemId */
/*
* 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) && ItemIdGetLength(itemId) == 0)
if (!ItemIdIsUsed(itemId) && !ItemIdHasStorage(itemId))
break;
}
if (offsetNumber >= limit)
@@ -224,9 +228,7 @@ PageAddItem(Page page,
(limit - offsetNumber) * sizeof(ItemIdData));
/* set the item pointer */
itemId->lp_off = upper;
itemId->lp_len = size;
itemId->lp_flags = flags;
ItemIdSetNormal(itemId, upper, size);
/* copy the item's data onto the page */
memcpy((char *) page + upper, item, size);
@@ -326,6 +328,7 @@ PageRepairFragmentation(Page page, OffsetNumber *unused)
itemidptr;
ItemId lp;
int nline,
nstorage,
nused;
int i;
Size totallen;
@@ -349,38 +352,41 @@ PageRepairFragmentation(Page page, OffsetNumber *unused)
pd_lower, pd_upper, pd_special)));
nline = PageGetMaxOffsetNumber(page);
nused = 0;
nused = nstorage = 0;
for (i = 0; i < nline; i++)
{
lp = PageGetItemId(page, i + 1);
if (ItemIdDeleted(lp)) /* marked for deletion */
lp->lp_flags &= ~(LP_USED | LP_DELETE);
if (ItemIdIsUsed(lp))
{
nused++;
else if (unused)
unused[i - nused] = (OffsetNumber) i;
if (ItemIdHasStorage(lp))
nstorage++;
}
else
{
/* Unused entries should have lp_len = 0, but make sure */
ItemIdSetUnused(lp);
/* Report to caller if asked for */
if (unused)
unused[i - nused] = (OffsetNumber) i;
}
}
if (nused == 0)
if (nstorage == 0)
{
/* Page is completely empty, so just reset it quickly */
for (i = 0; i < nline; i++)
{
lp = PageGetItemId(page, i + 1);
lp->lp_len = 0; /* indicate unused & deallocated */
}
((PageHeader) page)->pd_upper = pd_special;
}
else
{ /* nused != 0 */
{ /* nstorage != 0 */
/* Need to compact the page the hard way */
itemidbase = (itemIdSort) palloc(sizeof(itemIdSortData) * nused);
itemidbase = (itemIdSort) palloc(sizeof(itemIdSortData) * nstorage);
itemidptr = itemidbase;
totallen = 0;
for (i = 0; i < nline; i++)
{
lp = PageGetItemId(page, i + 1);
if (ItemIdIsUsed(lp))
if (ItemIdHasStorage(lp))
{
itemidptr->offsetindex = i;
itemidptr->itemoff = ItemIdGetOffset(lp);
@@ -394,10 +400,6 @@ PageRepairFragmentation(Page page, OffsetNumber *unused)
totallen += itemidptr->alignedlen;
itemidptr++;
}
else
{
lp->lp_len = 0; /* indicate unused & deallocated */
}
}
if (totallen > (Size) (pd_special - pd_lower))
@@ -407,13 +409,13 @@ PageRepairFragmentation(Page page, OffsetNumber *unused)
(unsigned int) totallen, pd_special - pd_lower)));
/* sort itemIdSortData array into decreasing itemoff order */
qsort((char *) itemidbase, nused, sizeof(itemIdSortData),
qsort((char *) itemidbase, nstorage, sizeof(itemIdSortData),
itemoffcompare);
/* compactify page */
upper = pd_special;
for (i = 0, itemidptr = itemidbase; i < nused; i++, itemidptr++)
for (i = 0, itemidptr = itemidbase; i < nstorage; i++, itemidptr++)
{
lp = PageGetItemId(page, itemidptr->offsetindex + 1);
upper -= itemidptr->alignedlen;
@@ -520,6 +522,7 @@ PageIndexTupleDelete(Page page, OffsetNumber offnum)
offidx = offnum - 1;
tup = PageGetItemId(page, offnum);
Assert(ItemIdHasStorage(tup));
size = ItemIdGetLength(tup);
offset = ItemIdGetOffset(tup);
@@ -577,6 +580,7 @@ PageIndexTupleDelete(Page page, OffsetNumber offnum)
{
ItemId ii = PageGetItemId(phdr, i);
Assert(ItemIdHasStorage(ii));
if (ItemIdGetOffset(ii) <= offset)
ii->lp_off += size;
}
@@ -654,6 +658,7 @@ PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems)
for (offnum = 1; offnum <= nline; offnum++)
{
lp = PageGetItemId(page, offnum);
Assert(ItemIdHasStorage(lp));
size = ItemIdGetLength(lp);
offset = ItemIdGetOffset(lp);
if (offset < pd_upper ||