item_size += IndexTupleSize(itup);
- if (!ItemIdDeleted(id))
+ if (!ItemIdIsDead(id))
stat->live_items++;
else
stat->dead_items++;
* Copyright (c) 2007, PostgreSQL Global Development Group
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/contrib/pageinspect/heapfuncs.c,v 1.1 2007/05/17 19:11:24 momjian Exp $
+ * $PostgreSQL: pgsql/contrib/pageinspect/heapfuncs.c,v 1.2 2007/09/12 22:10:25 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* could be corrupt in many other ways, but at least we won't
* crash.
*/
- if ((lp_len >= sizeof(HeapTupleHeader)) &&
- (lp_offset == MAXALIGN(lp_offset)) &&
- (lp_offset + lp_len <= raw_page_size) &&
- ItemIdIsUsed(id))
+ if (ItemIdHasStorage(id) &&
+ lp_len >= sizeof(HeapTupleHeader) &&
+ lp_offset == MAXALIGN(lp_offset) &&
+ lp_offset + lp_len <= raw_page_size)
{
HeapTupleHeader tuphdr;
int bits_len;
- /* Extract infromation from the tuple header */
+ /* Extract information from the tuple header */
tuphdr = (HeapTupleHeader) PageGetItem(page, id);
/*
- * $PostgreSQL: pgsql/contrib/pgstattuple/pgstattuple.c,v 1.28 2007/08/26 23:59:50 tgl Exp $
+ * $PostgreSQL: pgsql/contrib/pgstattuple/pgstattuple.c,v 1.29 2007/09/12 22:10:25 tgl Exp $
*
* Copyright (c) 2001,2002 Tatsuo Ishii
*
{
ItemId itemid = PageGetItemId(page, i);
- if (ItemIdDeleted(itemid))
+ if (ItemIdIsDead(itemid))
{
stat->dead_tuple_count++;
stat->dead_tuple_len += ItemIdGetLength(itemid);
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/gin/ginentrypage.c,v 1.7 2007/06/04 15:56:28 teodor Exp $
+ * $PostgreSQL: pgsql/src/backend/access/gin/ginentrypage.c,v 1.8 2007/09/12 22:10:25 tgl Exp $
*-------------------------------------------------------------------------
*/
*prdata = rdata;
data.updateBlkno = entryPreparePage(btree, page, off);
- placed = PageAddItem(page, (Item) btree->entry, IndexTupleSize(btree->entry), off, LP_USED);
+ placed = PageAddItem(page, (Item) btree->entry, IndexTupleSize(btree->entry), off, false);
if (placed != off)
elog(ERROR, "failed to add item to index page in \"%s\"",
RelationGetRelationName(btree->index));
lsize += MAXALIGN(IndexTupleSize(itup)) + sizeof(ItemIdData);
}
- if (PageAddItem(page, (Item) itup, IndexTupleSize(itup), InvalidOffsetNumber, LP_USED) == InvalidOffsetNumber)
+ if (PageAddItem(page, (Item) itup, IndexTupleSize(itup), InvalidOffsetNumber, false) == InvalidOffsetNumber)
elog(ERROR, "failed to add item to index page in \"%s\"",
RelationGetRelationName(btree->index));
ptr += MAXALIGN(IndexTupleSize(itup));
page = BufferGetPage(root);
itup = ginPageGetLinkItup(lbuf);
- if (PageAddItem(page, (Item) itup, IndexTupleSize(itup), InvalidOffsetNumber, LP_USED) == InvalidOffsetNumber)
+ if (PageAddItem(page, (Item) itup, IndexTupleSize(itup), InvalidOffsetNumber, false) == InvalidOffsetNumber)
elog(ERROR, "failed to add item to index root page");
itup = ginPageGetLinkItup(rbuf);
- if (PageAddItem(page, (Item) itup, IndexTupleSize(itup), InvalidOffsetNumber, LP_USED) == InvalidOffsetNumber)
+ if (PageAddItem(page, (Item) itup, IndexTupleSize(itup), InvalidOffsetNumber, false) == InvalidOffsetNumber)
elog(ERROR, "failed to add item to index root page");
}
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/gin/ginvacuum.c,v 1.15 2007/06/05 12:47:49 teodor Exp $
+ * $PostgreSQL: pgsql/src/backend/access/gin/ginvacuum.c,v 1.16 2007/09/12 22:10:25 tgl Exp $
*-------------------------------------------------------------------------
*/
itup = GinFormTuple(&gvs->ginstate, value, GinGetPosting(itup), newN);
PageIndexTupleDelete(tmppage, i);
- if (PageAddItem(tmppage, (Item) itup, IndexTupleSize(itup), i, LP_USED) != i)
+ if (PageAddItem(tmppage, (Item) itup, IndexTupleSize(itup), i, false) != i)
elog(ERROR, "failed to add item to index page in \"%s\"",
RelationGetRelationName(gvs->index));
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/gin/ginxlog.c,v 1.7 2007/06/04 15:56:28 teodor Exp $
+ * $PostgreSQL: pgsql/src/backend/access/gin/ginxlog.c,v 1.8 2007/09/12 22:10:25 tgl Exp $
*-------------------------------------------------------------------------
*/
#include "postgres.h"
itup = (IndexTuple) (XLogRecGetData(record) + sizeof(ginxlogInsert));
- if (PageAddItem(page, (Item) itup, IndexTupleSize(itup), data->offset, LP_USED) == InvalidOffsetNumber)
+ if (PageAddItem(page, (Item) itup, IndexTupleSize(itup), data->offset, false) == InvalidOffsetNumber)
elog(ERROR, "failed to add item to index page in %u/%u/%u",
data->node.spcNode, data->node.dbNode, data->node.relNode);
for (i = 0; i < data->separator; i++)
{
- if (PageAddItem(lpage, (Item) itup, IndexTupleSize(itup), InvalidOffsetNumber, LP_USED) == InvalidOffsetNumber)
+ if (PageAddItem(lpage, (Item) itup, IndexTupleSize(itup), InvalidOffsetNumber, false) == InvalidOffsetNumber)
elog(ERROR, "failed to add item to index page in %u/%u/%u",
data->node.spcNode, data->node.dbNode, data->node.relNode);
itup = (IndexTuple) (((char *) itup) + MAXALIGN(IndexTupleSize(itup)));
for (i = data->separator; i < data->nitem; i++)
{
- if (PageAddItem(rpage, (Item) itup, IndexTupleSize(itup), InvalidOffsetNumber, LP_USED) == InvalidOffsetNumber)
+ if (PageAddItem(rpage, (Item) itup, IndexTupleSize(itup), InvalidOffsetNumber, false) == InvalidOffsetNumber)
elog(ERROR, "failed to add item to index page in %u/%u/%u",
data->node.spcNode, data->node.dbNode, data->node.relNode);
itup = (IndexTuple) (((char *) itup) + MAXALIGN(IndexTupleSize(itup)));
for (i = 0; i < data->nitem; i++)
{
- if (PageAddItem(page, (Item) itup, IndexTupleSize(itup), InvalidOffsetNumber, LP_USED) == InvalidOffsetNumber)
+ if (PageAddItem(page, (Item) itup, IndexTupleSize(itup), InvalidOffsetNumber, false) == InvalidOffsetNumber)
elog(ERROR, "failed to add item to index page in %u/%u/%u",
data->node.spcNode, data->node.dbNode, data->node.relNode);
itup = (IndexTuple) (((char *) itup) + MAXALIGN(IndexTupleSize(itup)));
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/gist/gist.c,v 1.145 2007/01/05 22:19:21 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/access/gist/gist.c,v 1.146 2007/09/12 22:10:25 tgl Exp $
*
*-------------------------------------------------------------------------
*/
data = (char *) (ptr->list);
for (i = 0; i < ptr->block.num; i++)
{
- if (PageAddItem(ptr->page, (Item) data, IndexTupleSize((IndexTuple) data), i + FirstOffsetNumber, LP_USED) == InvalidOffsetNumber)
+ if (PageAddItem(ptr->page, (Item) data, IndexTupleSize((IndexTuple) data), i + FirstOffsetNumber, false) == InvalidOffsetNumber)
elog(ERROR, "failed to add item to index page in \"%s\"", RelationGetRelationName(state->r));
data += IndexTupleSize((IndexTuple) data);
}
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/gist/gistget.c,v 1.66 2007/05/27 03:50:38 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/gist/gistget.c,v 1.67 2007/09/12 22:10:25 tgl Exp $
*
*-------------------------------------------------------------------------
*/
{
/* page unchanged, so all is simple */
offset = ItemPointerGetOffsetNumber(iptr);
- PageGetItemId(p, offset)->lp_flags |= LP_DELETE;
+ ItemIdMarkDead(PageGetItemId(p, offset));
SetBufferCommitInfoNeedsSave(buffer);
LockBuffer(buffer, GIST_UNLOCK);
break;
if (ItemPointerEquals(&(ituple->t_tid), iptr))
{
/* found */
- PageGetItemId(p, offset)->lp_flags |= LP_DELETE;
+ ItemIdMarkDead(PageGetItemId(p, offset));
SetBufferCommitInfoNeedsSave(buffer);
LockBuffer(buffer, GIST_UNLOCK);
if (buffer != so->curbuf)
ItemPointerSet(&(so->curpos),
BufferGetBlockNumber(so->curbuf), n);
- if (!(ignore_killed_tuples && ItemIdDeleted(PageGetItemId(p, n))))
+ if (!(ignore_killed_tuples && ItemIdIsDead(PageGetItemId(p, n))))
{
it = (IndexTuple) PageGetItem(p, PageGetItemId(p, n));
tids[ntids] = scan->xs_ctup.t_self = it->t_tid;
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/gist/gistutil.c,v 1.22 2007/04/09 22:03:57 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/gist/gistutil.c,v 1.23 2007/09/12 22:10:25 tgl Exp $
*-------------------------------------------------------------------------
*/
#include "postgres.h"
for (i = 0; i < len; i++)
{
l = PageAddItem(page, (Item) itup[i], IndexTupleSize(itup[i]),
- off, LP_USED);
+ off, false);
if (l == InvalidOffsetNumber)
elog(ERROR, "failed to add item to index page in \"%s\"",
RelationGetRelationName(r));
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/gist/gistvacuum.c,v 1.30 2007/05/31 14:03:09 teodor Exp $
+ * $PostgreSQL: pgsql/src/backend/access/gist/gistvacuum.c,v 1.31 2007/09/12 22:10:25 tgl Exp $
*
*-------------------------------------------------------------------------
*/
data = (char *) (ptr->list);
for (i = 0; i < ptr->block.num; i++)
{
- if (PageAddItem(ptr->page, (Item) data, IndexTupleSize((IndexTuple) data), i + FirstOffsetNumber, LP_USED) == InvalidOffsetNumber)
+ if (PageAddItem(ptr->page, (Item) data, IndexTupleSize((IndexTuple) data), i + FirstOffsetNumber, false) == InvalidOffsetNumber)
elog(ERROR, "failed to add item to index page in \"%s\"", RelationGetRelationName(gv->index));
data += IndexTupleSize((IndexTuple) data);
}
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/hash/hash.c,v 1.95 2007/05/30 20:11:51 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/hash/hash.c,v 1.96 2007/09/12 22:10:25 tgl Exp $
*
* NOTES
* This file contains only the public interface routines.
if (scan->kill_prior_tuple)
{
/*
- * Yes, so mark it by setting the LP_DELETE bit in the item flags.
+ * Yes, so mark it by setting the LP_DEAD state in the item flags.
*/
offnum = ItemPointerGetOffsetNumber(&(so->hashso_curpos));
page = BufferGetPage(so->hashso_curbuf);
- PageGetItemId(page, offnum)->lp_flags |= LP_DELETE;
+ ItemIdMarkDead(PageGetItemId(page, offnum));
/*
* Since this can be redone later if needed, it's treated the same
{
offnum = ItemPointerGetOffsetNumber(&(so->hashso_curpos));
page = BufferGetPage(so->hashso_curbuf);
- if (!ItemIdDeleted(PageGetItemId(page, offnum)))
+ if (!ItemIdIsDead(PageGetItemId(page, offnum)))
break;
res = _hash_next(scan, dir);
}
offnum = ItemPointerGetOffsetNumber(&(so->hashso_curpos));
page = BufferGetPage(so->hashso_curbuf);
- if (!ItemIdDeleted(PageGetItemId(page, offnum)))
+ if (!ItemIdIsDead(PageGetItemId(page, offnum)))
break;
res = _hash_next(scan, ForwardScanDirection);
}
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/hash/hashinsert.c,v 1.45 2007/05/03 16:45:58 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/hash/hashinsert.c,v 1.46 2007/09/12 22:10:25 tgl Exp $
*
*-------------------------------------------------------------------------
*/
page = BufferGetPage(buf);
itup_off = OffsetNumberNext(PageGetMaxOffsetNumber(page));
- if (PageAddItem(page, (Item) itup, itemsize, itup_off, LP_USED)
+ if (PageAddItem(page, (Item) itup, itemsize, itup_off, false)
== InvalidOffsetNumber)
elog(ERROR, "failed to add index item to \"%s\"",
RelationGetRelationName(rel));
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/hash/hashovfl.c,v 1.58 2007/05/30 20:11:51 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/hash/hashovfl.c,v 1.59 2007/09/12 22:10:25 tgl Exp $
*
* NOTES
* Overflow pages look like ordinary relation pages.
* we have found room so insert on the "write" page.
*/
woffnum = OffsetNumberNext(PageGetMaxOffsetNumber(wpage));
- if (PageAddItem(wpage, (Item) itup, itemsz, woffnum, LP_USED)
+ if (PageAddItem(wpage, (Item) itup, itemsz, woffnum, false)
== InvalidOffsetNumber)
elog(ERROR, "failed to add index item to \"%s\"",
RelationGetRelationName(rel));
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/hash/hashpage.c,v 1.68 2007/05/30 20:11:51 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/hash/hashpage.c,v 1.69 2007/09/12 22:10:25 tgl Exp $
*
* NOTES
* Postgres hash pages look like ordinary relation pages. The opaque
}
noffnum = OffsetNumberNext(PageGetMaxOffsetNumber(npage));
- if (PageAddItem(npage, (Item) itup, itemsz, noffnum, LP_USED)
+ if (PageAddItem(npage, (Item) itup, itemsz, noffnum, false)
== InvalidOffsetNumber)
elog(ERROR, "failed to add index item to \"%s\"",
RelationGetRelationName(rel));
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.239 2007/09/07 20:59:26 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.240 2007/09/12 22:10:26 tgl Exp $
*
*
* INTERFACE ROUTINES
lineoff <= lines;
lineoff++, lpp++)
{
- if (ItemIdIsUsed(lpp))
+ if (ItemIdIsNormal(lpp))
{
HeapTupleData loctup;
bool valid;
{
while (linesleft > 0)
{
- if (ItemIdIsUsed(lpp))
+ if (ItemIdIsNormal(lpp))
{
bool valid;
{
lineoff = scan->rs_vistuples[lineindex];
lpp = PageGetItemId(dp, lineoff);
- Assert(ItemIdIsUsed(lpp));
+ Assert(ItemIdIsNormal(lpp));
tuple->t_data = (HeapTupleHeader) PageGetItem((Page) dp, lpp);
tuple->t_len = ItemIdGetLength(lpp);
/*
* Must check for deleted tuple.
*/
- if (!ItemIdIsUsed(lp))
+ if (!ItemIdIsNormal(lp))
{
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
if (keep_buf)
break;
}
lp = PageGetItemId(dp, offnum);
- if (!ItemIdIsUsed(lp))
+ if (!ItemIdIsNormal(lp))
{
UnlockReleaseBuffer(buffer);
break;
dp = (PageHeader) BufferGetPage(buffer);
lp = PageGetItemId(dp, ItemPointerGetOffsetNumber(tid));
+ Assert(ItemIdIsNormal(lp));
tp.t_data = (HeapTupleHeader) PageGetItem(dp, lp);
tp.t_len = ItemIdGetLength(lp);
dp = (PageHeader) BufferGetPage(buffer);
lp = PageGetItemId(dp, ItemPointerGetOffsetNumber(otid));
+ Assert(ItemIdIsNormal(lp));
oldtup.t_data = (HeapTupleHeader) PageGetItem(dp, lp);
oldtup.t_len = ItemIdGetLength(lp);
dp = (PageHeader) BufferGetPage(*buffer);
lp = PageGetItemId(dp, ItemPointerGetOffsetNumber(tid));
- Assert(ItemIdIsUsed(lp));
+ Assert(ItemIdIsNormal(lp));
tuple->t_data = (HeapTupleHeader) PageGetItem((Page) dp, lp);
tuple->t_len = ItemIdGetLength(lp);
if (PageGetMaxOffsetNumber(page) >= offnum)
lp = PageGetItemId(page, offnum);
- if (PageGetMaxOffsetNumber(page) < offnum || !ItemIdIsUsed(lp))
+ if (PageGetMaxOffsetNumber(page) < offnum || !ItemIdIsNormal(lp))
elog(ERROR, "heap_inplace_update: invalid lp");
htup = (HeapTupleHeader) PageGetItem(page, lp);
{
/* unused[] entries are zero-based */
lp = PageGetItemId(page, *unused + 1);
- lp->lp_flags &= ~LP_USED;
+ ItemIdSetUnused(lp);
unused++;
}
}
if (PageGetMaxOffsetNumber(page) >= offnum)
lp = PageGetItemId(page, offnum);
- if (PageGetMaxOffsetNumber(page) < offnum || !ItemIdIsUsed(lp))
+ if (PageGetMaxOffsetNumber(page) < offnum || !ItemIdIsNormal(lp))
elog(PANIC, "heap_delete_redo: invalid lp");
htup = (HeapTupleHeader) PageGetItem(page, lp);
HeapTupleHeaderSetCmin(htup, FirstCommandId);
htup->t_ctid = xlrec->target.tid;
- offnum = PageAddItem(page, (Item) htup, newlen, offnum,
- LP_USED | OverwritePageMode);
+ offnum = PageAddItem(page, (Item) htup, newlen, offnum, true);
if (offnum == InvalidOffsetNumber)
elog(PANIC, "heap_insert_redo: failed to add tuple");
PageSetLSN(page, lsn);
if (PageGetMaxOffsetNumber(page) >= offnum)
lp = PageGetItemId(page, offnum);
- if (PageGetMaxOffsetNumber(page) < offnum || !ItemIdIsUsed(lp))
+ if (PageGetMaxOffsetNumber(page) < offnum || !ItemIdIsNormal(lp))
elog(PANIC, "heap_update_redo: invalid lp");
htup = (HeapTupleHeader) PageGetItem(page, lp);
/* Make sure there is no forward chain link in t_ctid */
htup->t_ctid = xlrec->newtid;
- offnum = PageAddItem(page, (Item) htup, newlen, offnum,
- LP_USED | OverwritePageMode);
+ offnum = PageAddItem(page, (Item) htup, newlen, offnum, true);
if (offnum == InvalidOffsetNumber)
elog(PANIC, "heap_update_redo: failed to add tuple");
PageSetLSN(page, lsn);
if (PageGetMaxOffsetNumber(page) >= offnum)
lp = PageGetItemId(page, offnum);
- if (PageGetMaxOffsetNumber(page) < offnum || !ItemIdIsUsed(lp))
+ if (PageGetMaxOffsetNumber(page) < offnum || !ItemIdIsNormal(lp))
elog(PANIC, "heap_lock_redo: invalid lp");
htup = (HeapTupleHeader) PageGetItem(page, lp);
if (PageGetMaxOffsetNumber(page) >= offnum)
lp = PageGetItemId(page, offnum);
- if (PageGetMaxOffsetNumber(page) < offnum || !ItemIdIsUsed(lp))
+ if (PageGetMaxOffsetNumber(page) < offnum || !ItemIdIsNormal(lp))
elog(PANIC, "heap_inplace_redo: invalid lp");
htup = (HeapTupleHeader) PageGetItem(page, lp);
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/heap/hio.c,v 1.65 2007/02/05 04:22:18 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/heap/hio.c,v 1.66 2007/09/12 22:10:26 tgl Exp $
*
*-------------------------------------------------------------------------
*/
pageHeader = BufferGetPage(buffer);
offnum = PageAddItem(pageHeader, (Item) tuple->t_data,
- tuple->t_len, InvalidOffsetNumber, LP_USED);
+ tuple->t_len, InvalidOffsetNumber, false);
if (offnum == InvalidOffsetNumber)
elog(PANIC, "failed to add tuple to page");
* Portions Copyright (c) 1994-5, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/heap/rewriteheap.c,v 1.5 2007/05/17 15:28:29 alvherre Exp $
+ * $PostgreSQL: pgsql/src/backend/access/heap/rewriteheap.c,v 1.6 2007/09/12 22:10:26 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/* And now we can insert the tuple into the page */
newoff = PageAddItem(page, (Item) heaptup->t_data, len,
- InvalidOffsetNumber, LP_USED);
+ InvalidOffsetNumber, false);
if (newoff == InvalidOffsetNumber)
elog(ERROR, "failed to add tuple");
-$PostgreSQL: pgsql/src/backend/access/nbtree/README,v 1.17 2007/01/12 17:04:54 tgl Exp $
+$PostgreSQL: pgsql/src/backend/access/nbtree/README,v 1.18 2007/09/12 22:10:26 tgl Exp $
This directory contains a correct implementation of Lehman and Yao's
high-concurrency B-tree management algorithm (P. Lehman and S. Yao,
(ie, dead to all open transactions, not only that process), then we can
return to the index and mark the corresponding index entry "known dead",
allowing subsequent index scans to skip visiting the heap tuple. The
-"known dead" marking uses the LP_DELETE bit in ItemIds. This is currently
-only done in plain indexscans, not bitmap scans, because only plain scans
-visit the heap and index "in sync" and so there's not a convenient way
-to do it for bitmap scans.
+"known dead" marking works by setting the index item's lp_flags state
+to LP_DEAD. This is currently only done in plain indexscans, not bitmap
+scans, because only plain scans visit the heap and index "in sync" and so
+there's not a convenient way to do it for bitmap scans.
-Once an index tuple has been marked LP_DELETE it can actually be removed
+Once an index tuple has been marked LP_DEAD it can actually be removed
from the index immediately; since index scans only stop "between" pages,
no scan can lose its place from such a deletion. We separate the steps
-because we allow LP_DELETE to be set with only a share lock (it's exactly
+because we allow LP_DEAD to be set with only a share lock (it's exactly
like a hint bit for a heap tuple), but physically removing tuples requires
-exclusive lock. In the current code we try to remove LP_DELETE tuples when
+exclusive lock. In the current code we try to remove LP_DEAD tuples when
we are otherwise faced with having to split a page to do an insertion (and
hence have exclusive lock on it already).
tuples into the index.)
It's sufficient to have an exclusive lock on the index page, not a
-super-exclusive lock, to do deletion of LP_DELETE items. It might seem
+super-exclusive lock, to do deletion of LP_DEAD items. It might seem
that this breaks the interlock between VACUUM and indexscans, but that is
not so: as long as an indexscanning process has a pin on the page where
the index item used to be, VACUUM cannot complete its btbulkdelete scan
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.158 2007/06/03 22:16:02 petere Exp $
+ * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.159 2007/09/12 22:10:26 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* we can. We only apply _bt_isequal() when we get to a non-killed
* item or the end of the page.
*/
- if (!ItemIdDeleted(curitemid))
+ if (!ItemIdIsDead(curitemid))
{
/*
* _bt_compare returns 0 for (1,NULL) and (1,NULL) - this's
if (HeapTupleSatisfiesVacuum(htup.t_data, RecentGlobalXmin,
hbuffer) == HEAPTUPLE_DEAD)
{
- curitemid->lp_flags |= LP_DELETE;
+ ItemIdMarkDead(curitemid);
opaque->btpo_flags |= BTP_HAS_GARBAGE;
/* be sure to mark the proper buffer dirty... */
if (nbuf != InvalidBuffer)
* any existing equal keys because of the way _bt_binsrch() works.
*
* If there's not enough room in the space, we try to make room by
- * removing any LP_DELETEd tuples.
+ * removing any LP_DEAD tuples.
*
* On entry, *buf and *offsetptr point to the first legal position
* where the new tuple could be inserted. The caller should hold an
/*
* before considering moving right, see if we can obtain enough
- * space by erasing LP_DELETE items
+ * space by erasing LP_DEAD items
*/
if (P_ISLEAF(lpageop) && P_HAS_GARBAGE(lpageop))
{
itemsz = ItemIdGetLength(itemid);
item = (IndexTuple) PageGetItem(origpage, itemid);
if (PageAddItem(rightpage, (Item) item, itemsz, rightoff,
- LP_USED) == InvalidOffsetNumber)
+ false) == InvalidOffsetNumber)
elog(PANIC, "failed to add hikey to the right sibling");
rightoff = OffsetNumberNext(rightoff);
}
item = (IndexTuple) PageGetItem(origpage, itemid);
}
if (PageAddItem(leftpage, (Item) item, itemsz, leftoff,
- LP_USED) == InvalidOffsetNumber)
+ false) == InvalidOffsetNumber)
elog(PANIC, "failed to add hikey to the left sibling");
leftoff = OffsetNumberNext(leftoff);
* Note: we *must* insert the two items in item-number order, for the
* benefit of _bt_restore_page().
*/
- if (PageAddItem(rootpage, (Item) new_item, itemsz, P_HIKEY, LP_USED) == InvalidOffsetNumber)
+ if (PageAddItem(rootpage, (Item) new_item, itemsz, P_HIKEY,
+ false) == InvalidOffsetNumber)
elog(PANIC, "failed to add leftkey to new root page");
pfree(new_item);
/*
* insert the right page pointer into the new root page.
*/
- if (PageAddItem(rootpage, (Item) new_item, itemsz, P_FIRSTKEY, LP_USED) == InvalidOffsetNumber)
+ if (PageAddItem(rootpage, (Item) new_item, itemsz, P_FIRSTKEY,
+ false) == InvalidOffsetNumber)
elog(PANIC, "failed to add rightkey to new root page");
pfree(new_item);
}
if (PageAddItem(page, (Item) itup, itemsize, itup_off,
- LP_USED) == InvalidOffsetNumber)
+ false) == InvalidOffsetNumber)
elog(PANIC, "failed to add item to the %s for \"%s\"",
where, RelationGetRelationName(rel));
}
/*
* _bt_vacuum_one_page - vacuum just one index page.
*
- * Try to remove LP_DELETE items from the given page. The passed buffer
+ * Try to remove LP_DEAD items from the given page. The passed buffer
* must be exclusive-locked, but unlike a real VACUUM, we don't need a
* super-exclusive "cleanup" lock (see nbtree/README).
*/
/*
* Scan over all items to see which ones need to be deleted
- * according to LP_DELETE flags.
+ * according to LP_DEAD flags.
*/
minoff = P_FIRSTDATAKEY(opaque);
maxoff = PageGetMaxOffsetNumber(page);
{
ItemId itemId = PageGetItemId(page, offnum);
- if (ItemIdDeleted(itemId))
+ if (ItemIdIsDead(itemId))
deletable[ndeletable++] = offnum;
}
_bt_delitems(rel, buffer, deletable, ndeletable);
/*
- * Note: if we didn't find any LP_DELETE items, then the page's
+ * Note: if we didn't find any LP_DEAD items, then the page's
* BTP_HAS_GARBAGE hint bit is falsely set. We do not bother expending a
* separate write to clear it, however. We will clear it when we split
* the page.
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtpage.c,v 1.102 2007/01/05 22:19:23 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtpage.c,v 1.103 2007/09/12 22:10:26 tgl Exp $
*
* NOTES
* Postgres btree pages look like ordinary relation pages. The opaque
opaque->btpo_cycleid = 0;
/*
- * Mark the page as not containing any LP_DELETE items. This is not
+ * Mark the page as not containing any LP_DEAD items. This is not
* certainly true (there might be some that have recently been marked, but
* weren't included in our target-item list), but it will almost always be
* true and it doesn't seem worth an additional page scan to check it.
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsort.c,v 1.111 2007/04/08 01:26:27 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsort.c,v 1.112 2007/09/12 22:10:26 tgl Exp $
*
*-------------------------------------------------------------------------
*/
}
if (PageAddItem(page, (Item) itup, itemsize, itup_off,
- LP_USED) == InvalidOffsetNumber)
+ false) == InvalidOffsetNumber)
elog(ERROR, "failed to add item to the index page");
}
*/
hii = PageGetItemId(opage, P_HIKEY);
*hii = *ii;
- ii->lp_flags &= ~LP_USED;
+ ItemIdSetUnused(ii); /* redundant */
((PageHeader) opage)->pd_lower -= sizeof(ItemIdData);
/*
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtutils.c,v 1.85 2007/04/09 22:04:01 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtutils.c,v 1.86 2007/09/12 22:10:26 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* However, if this is the last tuple on the page, we should check the
* index keys to prevent uselessly advancing to the next page.
*/
- if (scan->ignore_killed_tuples && ItemIdDeleted(iid))
+ if (scan->ignore_killed_tuples && ItemIdIsDead(iid))
{
/* return immediately if there are more tuples on the page */
if (ScanDirectionIsForward(dir))
}
/*
- * _bt_killitems - set LP_DELETE bit for items an indexscan caller has
+ * _bt_killitems - set LP_DEAD state for items an indexscan caller has
* told us were killed
*
* scan->so contains information about the current page and killed tuples
*
* The caller must have pin on so->currPos.buf, but may or may not have
* read-lock, as indicated by haveLock. Note that we assume read-lock
- * is sufficient for setting LP_DELETE hint bits.
+ * is sufficient for setting LP_DEAD status (which is only a hint).
*
* We match items by heap TID before assuming they are the right ones to
* delete. We cope with cases where items have moved right due to insertions.
if (ItemPointerEquals(&ituple->t_tid, &kitem->heapTid))
{
/* found the item */
- iid->lp_flags |= LP_DELETE;
+ ItemIdMarkDead(iid);
killedsomething = true;
break; /* out of inner search loop */
}
* commit-hint-bit status update for heap tuples: we mark the buffer dirty
* but don't make a WAL log entry.
*
- * Whenever we mark anything LP_DELETEd, we also set the page's
+ * Whenever we mark anything LP_DEAD, we also set the page's
* BTP_HAS_GARBAGE flag, which is likewise just a hint.
*/
if (killedsomething)
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtxlog.c,v 1.44 2007/05/20 21:08:19 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtxlog.c,v 1.45 2007/09/12 22:10:26 tgl Exp $
*
*-------------------------------------------------------------------------
*/
itemsz = IndexTupleDSize(itupdata);
itemsz = MAXALIGN(itemsz);
if (PageAddItem(page, (Item) from, itemsz,
- FirstOffsetNumber, LP_USED) == InvalidOffsetNumber)
+ FirstOffsetNumber, false) == InvalidOffsetNumber)
elog(PANIC, "_bt_restore_page: cannot add item to page");
from += itemsz;
}
{
if (PageAddItem(page, (Item) datapos, datalen,
ItemPointerGetOffsetNumber(&(xlrec->target.tid)),
- LP_USED) == InvalidOffsetNumber)
+ false) == InvalidOffsetNumber)
elog(PANIC, "btree_insert_redo: failed to add item");
PageSetLSN(page, lsn);
if (onleft)
{
if (PageAddItem(lpage, newitem, newitemsz, newitemoff,
- LP_USED) == InvalidOffsetNumber)
+ false) == InvalidOffsetNumber)
elog(PANIC, "failed to add new item to left page after split");
}
hiItem = PageGetItem(rpage, hiItemId);
if (PageAddItem(lpage, hiItem, ItemIdGetLength(hiItemId),
- P_HIKEY, LP_USED) == InvalidOffsetNumber)
+ P_HIKEY, false) == InvalidOffsetNumber)
elog(PANIC, "failed to add high key to left page after split");
/* Fix opaque fields */
}
/*
- * Mark the page as not containing any LP_DELETE items --- see comments in
+ * Mark the page as not containing any LP_DEAD items --- see comments in
* _bt_delitems().
*/
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/sequence.c,v 1.144 2007/09/05 18:10:47 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/sequence.c,v 1.145 2007/09/12 22:10:26 tgl Exp $
*
*-------------------------------------------------------------------------
*/
RelationGetRelationName(rel), sm->magic);
lp = PageGetItemId(page, FirstOffsetNumber);
- Assert(ItemIdIsUsed(lp));
+ Assert(ItemIdIsNormal(lp));
tuple.t_data = (HeapTupleHeader) PageGetItem((Page) page, lp);
seq = (Form_pg_sequence) GETSTRUCT(&tuple);
itemsz = record->xl_len - sizeof(xl_seq_rec);
itemsz = MAXALIGN(itemsz);
if (PageAddItem(page, (Item) item, itemsz,
- FirstOffsetNumber, LP_USED) == InvalidOffsetNumber)
+ FirstOffsetNumber, false) == InvalidOffsetNumber)
elog(PANIC, "seq_redo: failed to add item to page");
PageSetLSN(page, lsn);
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.218 2007/08/15 21:39:50 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.219 2007/09/12 22:10:26 tgl Exp $
*
*-------------------------------------------------------------------------
*/
dp = (PageHeader) BufferGetPage(buffer);
lp = PageGetItemId(dp, ItemPointerGetOffsetNumber(tid));
- Assert(ItemIdIsUsed(lp));
+ Assert(ItemIdIsNormal(lp));
tuple.t_data = (HeapTupleHeader) PageGetItem((Page) dp, lp);
tuple.t_len = ItemIdGetLength(lp);
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.357 2007/09/08 20:31:14 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.358 2007/09/12 22:10:26 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/* mark it unused on the temp page */
lpp = PageGetItemId(tempPage, offnum);
- lpp->lp_flags &= ~LP_USED;
+ ItemIdSetUnused(lpp);
vacpage->offsets[vacpage->offsets_free++] = offnum;
tups_vacuumed += 1;
{
/* Just use current available space */
vacpage->free = PageGetFreeSpaceWithFillFactor(onerel, page);
- /* Need to reap the page if it has ~LP_USED line pointers */
+ /* Need to reap the page if it has LP_UNUSED line pointers */
do_reap = (vacpage->offsets_free > 0);
}
if (HeapTupleHeaderGetXvac(htup) != myXID)
elog(ERROR, "invalid XVAC in tuple header");
- itemid->lp_flags &= ~LP_USED;
+ ItemIdSetUnused(itemid);
num_tuples++;
}
Assert(vacpage->offsets_free == num_tuples);
newtup.t_data->t_infomask |= HEAP_MOVED_IN;
HeapTupleHeaderSetXvac(newtup.t_data, myXID);
newoff = PageAddItem(dst_page, (Item) newtup.t_data, tuple_len,
- InvalidOffsetNumber, LP_USED);
+ InvalidOffsetNumber, false);
if (newoff == InvalidOffsetNumber)
elog(PANIC, "failed to add item with len = %lu to page %u while moving tuple chain",
(unsigned long) tuple_len, dst_vacpage->blkno);
/* add tuple to the page */
newoff = PageAddItem(dst_page, (Item) newtup.t_data, tuple_len,
- InvalidOffsetNumber, LP_USED);
+ InvalidOffsetNumber, false);
if (newoff == InvalidOffsetNumber)
elog(PANIC, "failed to add item with len = %lu to page %u (free space %lu, nusd %u, noff %u)",
(unsigned long) tuple_len,
for (i = 0; i < vacpage->offsets_free; i++)
{
itemid = PageGetItemId(page, vacpage->offsets[i]);
- itemid->lp_flags &= ~LP_USED;
+ ItemIdSetUnused(itemid);
}
uncnt = PageRepairFragmentation(page, unused);
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.94 2007/09/12 02:05:48 alvherre Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.95 2007/09/12 22:10:26 tgl Exp $
*
*-------------------------------------------------------------------------
*/
break; /* past end of tuples for this block */
toff = ItemPointerGetOffsetNumber(&vacrelstats->dead_tuples[tupindex]);
itemid = PageGetItemId(page, toff);
- itemid->lp_flags &= ~LP_USED;
+ ItemIdSetUnused(itemid);
}
uncnt = PageRepairFragmentation(page, unused);
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeBitmapHeapscan.c,v 1.18 2007/06/09 18:49:55 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeBitmapHeapscan.c,v 1.19 2007/09/12 22:10:26 tgl Exp $
*
*-------------------------------------------------------------------------
*/
targoffset = scan->rs_vistuples[scan->rs_cindex];
dp = (Page) BufferGetPage(scan->rs_cbuf);
lp = PageGetItemId(dp, targoffset);
- Assert(ItemIdIsUsed(lp));
+ Assert(ItemIdIsNormal(lp));
scan->rs_ctup.t_data = (HeapTupleHeader) PageGetItem((Page) dp, lp);
scan->rs_ctup.t_len = ItemIdGetLength(lp);
/*
* Must check for deleted tuple.
*/
- if (!ItemIdIsUsed(lp))
+ if (!ItemIdIsNormal(lp))
continue;
/*
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
* 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
Item item,
Size size,
OffsetNumber offsetNumber,
- ItemIdFlags flags)
+ bool overwrite)
{
PageHeader phdr = (PageHeader) page;
Size alignedSize;
ItemId itemId;
OffsetNumber limit;
bool needshuffle = false;
- bool overwritemode = (flags & OverwritePageMode) != 0;
-
- flags &= ~OverwritePageMode;
/*
* Be wary about corrupted page pointers
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;
/* 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)
(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);
itemidptr;
ItemId lp;
int nline,
+ nstorage,
nused;
int i;
Size totallen;
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);
totallen += itemidptr->alignedlen;
itemidptr++;
}
- else
- {
- lp->lp_len = 0; /* indicate unused & deallocated */
- }
}
if (totallen > (Size) (pd_special - pd_lower))
(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;
offidx = offnum - 1;
tup = PageGetItemId(page, offnum);
+ Assert(ItemIdHasStorage(tup));
size = ItemIdGetLength(tup);
offset = ItemIdGetOffset(tup);
{
ItemId ii = PageGetItemId(phdr, i);
+ Assert(ItemIdHasStorage(ii));
if (ItemIdGetOffset(ii) <= offset)
ii->lp_off += size;
}
for (offnum = 1; offnum <= nline; offnum++)
{
lp = PageGetItemId(page, offnum);
+ Assert(ItemIdHasStorage(lp));
size = ItemIdGetLength(lp);
offset = ItemIdGetOffset(lp);
if (offset < pd_upper ||
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/storage/bufpage.h,v 1.72 2007/03/02 00:48:44 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/storage/bufpage.h,v 1.73 2007/09/12 22:10:26 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* pd_flags contains the following flag bits. Undefined bits are initialized
* to zero and may be used in the future.
*
- * PD_HAS_FREE_LINES is set if there are any not-LP_USED line pointers before
+ * PD_HAS_FREE_LINES is set if there are any LP_UNUSED line pointers before
* pd_lower. This should be considered a hint rather than the truth, since
* changes to it are not WAL-logged.
*/
#define PageGetItem(page, itemId) \
( \
AssertMacro(PageIsValid(page)), \
- AssertMacro(ItemIdIsUsed(itemId)), \
+ AssertMacro(ItemIdHasStorage(itemId)), \
(Item)(((char *)(page)) + ItemIdGetOffset(itemId)) \
)
extern void PageInit(Page page, Size pageSize, Size specialSize);
extern bool PageHeaderIsValid(PageHeader page);
extern OffsetNumber PageAddItem(Page page, Item item, Size size,
- OffsetNumber offsetNumber, ItemIdFlags flags);
+ OffsetNumber offsetNumber, bool overwrite);
extern Page PageGetTempPage(Page page, Size specialSize);
extern void PageRestoreTempPage(Page tempPage, Page oldPage);
extern int PageRepairFragmentation(Page page, OffsetNumber *unused);
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/storage/itemid.h,v 1.27 2007/01/05 22:19:58 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/storage/itemid.h,v 1.28 2007/09/12 22:10:26 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/*
* An item pointer (also called line pointer) on a buffer page
+ *
+ * In some cases an item pointer is "in use" but does not have any associated
+ * storage on the page. By convention, lp_len == 0 in every item pointer
+ * that does not have storage, independently of its lp_flags state.
*/
typedef struct ItemIdData
-{ /* line pointers */
- unsigned lp_off:15, /* offset to start of tuple */
- lp_flags:2, /* flags for tuple */
- lp_len:15; /* length of tuple */
+{
+ unsigned lp_off:15, /* offset to tuple (from start of page) */
+ lp_flags:2, /* state of item pointer, see below */
+ lp_len:15; /* byte length of tuple */
} ItemIdData;
typedef ItemIdData *ItemId;
/*
- * lp_flags contains these flags:
- */
-#define LP_USED 0x01 /* this line pointer is being used */
-
-#define LP_DELETE 0x02 /* item is to be deleted */
-
-#define ItemIdDeleted(itemId) \
- (((itemId)->lp_flags & LP_DELETE) != 0)
-
-/*
- * This bit may be passed to PageAddItem together with
- * LP_USED & LP_DELETE bits to specify overwrite mode
+ * lp_flags has these possible states. An UNUSED line pointer is available
+ * for immediate re-use, the other states are not.
*/
-#define OverwritePageMode 0x10
+#define LP_UNUSED 0 /* unused (should always have lp_len=0) */
+#define LP_NORMAL 1 /* used (should always have lp_len>0) */
+#define LP_REDIRECT 2 /* HOT redirect (should have lp_len=0) */
+#define LP_DEAD 3 /* dead, may or may not have storage */
/*
- * Item offsets, lengths, and flags are represented by these types when
+ * Item offsets and lengths are represented by these types when
* they're not actually stored in an ItemIdData.
*/
typedef uint16 ItemOffset;
typedef uint16 ItemLength;
-typedef bits16 ItemIdFlags;
-
/* ----------------
* support macros
#define ItemIdGetFlags(itemId) \
((itemId)->lp_flags)
+/*
+ * ItemIdGetRedirect
+ * In a REDIRECT pointer, lp_off holds the link to the next item pointer
+ */
+#define ItemIdGetRedirect(itemId) \
+ ((itemId)->lp_off)
+
/*
* ItemIdIsValid
- * True iff disk item identifier is valid.
+ * True iff item identifier is valid.
+ * This is a pretty weak test, probably useful only in Asserts.
*/
#define ItemIdIsValid(itemId) PointerIsValid(itemId)
/*
* ItemIdIsUsed
- * True iff disk item identifier is in use.
- *
- * Note:
- * Assumes disk item identifier is valid.
+ * True iff item identifier is in use.
*/
#define ItemIdIsUsed(itemId) \
+ ((itemId)->lp_flags != LP_UNUSED)
+
+/*
+ * ItemIdIsNormal
+ * True iff item identifier is in state NORMAL.
+ */
+#define ItemIdIsNormal(itemId) \
+ ((itemId)->lp_flags == LP_NORMAL)
+
+/*
+ * ItemIdIsRedirected
+ * True iff item identifier is in state REDIRECT.
+ */
+#define ItemIdIsRedirected(itemId) \
+ ((itemId)->lp_flags == LP_REDIRECT)
+
+/*
+ * ItemIdIsDead
+ * True iff item identifier is in state DEAD.
+ */
+#define ItemIdIsDead(itemId) \
+ ((itemId)->lp_flags == LP_DEAD)
+
+/*
+ * ItemIdHasStorage
+ * True iff item identifier has associated storage.
+ */
+#define ItemIdHasStorage(itemId) \
+ ((itemId)->lp_len != 0)
+
+/*
+ * ItemIdSetUnused
+ * Set the item identifier to be UNUSED, with no storage.
+ * Beware of multiple evaluations of itemId!
+ */
+#define ItemIdSetUnused(itemId) \
+( \
+ (itemId)->lp_flags = LP_UNUSED, \
+ (itemId)->lp_off = 0, \
+ (itemId)->lp_len = 0 \
+)
+
+/*
+ * ItemIdSetNormal
+ * Set the item identifier to be NORMAL, with the specified storage.
+ * Beware of multiple evaluations of itemId!
+ */
+#define ItemIdSetNormal(itemId, off, len) \
+( \
+ (itemId)->lp_flags = LP_NORMAL, \
+ (itemId)->lp_off = (off), \
+ (itemId)->lp_len = (len) \
+)
+
+/*
+ * ItemIdSetRedirect
+ * Set the item identifier to be REDIRECT, with the specified link.
+ * Beware of multiple evaluations of itemId!
+ */
+#define ItemIdSetRedirect(itemId, link) \
+( \
+ (itemId)->lp_flags = LP_REDIRECT, \
+ (itemId)->lp_off = (link), \
+ (itemId)->lp_len = 0 \
+)
+
+/*
+ * ItemIdSetDead
+ * Set the item identifier to be DEAD, with no storage.
+ * Beware of multiple evaluations of itemId!
+ */
+#define ItemIdSetDead(itemId) \
+( \
+ (itemId)->lp_flags = LP_DEAD, \
+ (itemId)->lp_off = 0, \
+ (itemId)->lp_len = 0 \
+)
+
+/*
+ * ItemIdMarkDead
+ * Set the item identifier to be DEAD, keeping its existing storage.
+ *
+ * Note: in indexes, this is used as if it were a hint-bit mechanism;
+ * we trust that multiple processors can do this in parallel and get
+ * the same result.
+ */
+#define ItemIdMarkDead(itemId) \
( \
- AssertMacro(ItemIdIsValid(itemId)), \
- (bool) (((itemId)->lp_flags & LP_USED) != 0) \
+ (itemId)->lp_flags = LP_DEAD \
)
#endif /* ITEMID_H */