diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2007-09-12 22:10:26 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2007-09-12 22:10:26 +0000 |
commit | 6889303531187f7867a5dfad5f5b5ba103f7cdd6 (patch) | |
tree | ea862682de0eb2dad6cba22fb7d0978d70fd54b2 /src/backend/storage/page/bufpage.c | |
parent | eb0a7735ba1ede6a35b80d73f6c371a8b1220552 (diff) | |
download | postgresql-6889303531187f7867a5dfad5f5b5ba103f7cdd6.tar.gz postgresql-6889303531187f7867a5dfad5f5b5ba103f7cdd6.zip |
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.
Diffstat (limited to 'src/backend/storage/page/bufpage.c')
-rw-r--r-- | src/backend/storage/page/bufpage.c | 71 |
1 files changed, 38 insertions, 33 deletions
diff --git a/src/backend/storage/page/bufpage.c b/src/backend/storage/page/bufpage.c index b246b0afeb8..3ce2f04bd8e 100644 --- a/src/backend/storage/page/bufpage.c +++ b/src/backend/storage/page/bufpage.c @@ -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 || |