本文整理汇总了C++中P_FIRSTDATAKEY函数的典型用法代码示例。如果您正苦于以下问题:C++ P_FIRSTDATAKEY函数的具体用法?C++ P_FIRSTDATAKEY怎么用?C++ P_FIRSTDATAKEY使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了P_FIRSTDATAKEY函数的20个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于我们的系统推荐出更棒的C++代码示例。
示例1: BTReaderGetNextItem
/**
* @brief Get the next smaller item from the old index
*
* Process flow
* -# Examine the max offset position in the page
* -# Search the next item
* -# If the item has deleted flag, seearch the next one
* -# If we can't find items any more, read the leaf page on the right side
* and search the next again
*
* These members are updated:
* - page : page which includes picked-up item
* - offnum : item offset number of the picked-up item
*
* @param reader [in/out] BTReader structure
* @return next index tuple, or null if no more tuples
*/
static IndexTuple
BTReaderGetNextItem(BTReader *reader)
{
OffsetNumber maxoff;
ItemId itemid;
BTPageOpaque opaque;
/*
* If any leaf page isn't read, the state is treated like as EOF
*/
if (reader->blkno == InvalidBlockNumber)
return NULL;
maxoff = PageGetMaxOffsetNumber(reader->page);
for (;;)
{
/*
* If no one items are picked up, offnum is set to InvalidOffsetNumber.
*/
if (reader->offnum == InvalidOffsetNumber)
{
opaque = (BTPageOpaque) PageGetSpecialPointer(reader->page);
reader->offnum = P_FIRSTDATAKEY(opaque);
}
else
reader->offnum = OffsetNumberNext(reader->offnum);
if (reader->offnum <= maxoff)
{
itemid = PageGetItemId(reader->page, reader->offnum);
/* Ignore dead items */
if (ItemIdIsDead(itemid))
continue;
return (IndexTuple) PageGetItem(reader->page, itemid);
}
else
{
/* The end of the leaf page. Go right. */
opaque = (BTPageOpaque) PageGetSpecialPointer(reader->page);
if (P_RIGHTMOST(opaque))
return NULL; /* No more index tuples */
BTReaderReadPage(reader, opaque->btpo_next);
maxoff = PageGetMaxOffsetNumber(reader->page);
}
}
}
开发者ID:chuongnn,项目名称:pg_bulkload,代码行数:68,代码来源:pg_btree.c
示例2: pgstat_btree_page
/*
* pgstat_btree_page -- check tuples in a btree page
*/
static void
pgstat_btree_page(pgstattuple_type *stat, Relation rel, BlockNumber blkno,
BufferAccessStrategy bstrategy)
{
Buffer buf;
Page page;
buf = ReadBufferExtended(rel, MAIN_FORKNUM, blkno, RBM_NORMAL, bstrategy);
LockBuffer(buf, BT_READ);
page = BufferGetPage(buf);
/* Page is valid, see what to do with it */
if (PageIsNew(page))
{
/* fully empty page */
stat->free_space += BLCKSZ;
}
else
{
BTPageOpaque opaque;
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
if (opaque->btpo_flags & (BTP_DELETED | BTP_HALF_DEAD))
{
/* recyclable page */
stat->free_space += BLCKSZ;
}
else if (P_ISLEAF(opaque))
{
pgstat_index_page(stat, page, P_FIRSTDATAKEY(opaque),
PageGetMaxOffsetNumber(page));
}
else
{
/* root or node */
}
}
_bt_relbuf(rel, buf);
}
开发者ID:gencer,项目名称:postgres,代码行数:43,代码来源:pgstattuple.c
示例3: _bt_step
/*
* _bt_step() -- Step one item in the requested direction in a scan on
* the tree.
*
* *bufP is the current buffer (read-locked and pinned). If we change
* pages, it's updated appropriately.
*
* If successful, update scan's currentItemData and return true.
* If no adjacent record exists in the requested direction,
* release buffer pin/locks and return false.
*/
bool
_bt_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir)
{
Relation rel = scan->indexRelation;
ItemPointer current = &(scan->currentItemData);
BTScanOpaque so = (BTScanOpaque) scan->opaque;
Page page;
BTPageOpaque opaque;
OffsetNumber offnum,
maxoff;
BlockNumber blkno;
/*
* Don't use ItemPointerGetOffsetNumber or you risk to get assertion
* due to ability of ip_posid to be equal 0.
*/
offnum = current->ip_posid;
page = BufferGetPage(*bufP);
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
maxoff = PageGetMaxOffsetNumber(page);
if (ScanDirectionIsForward(dir))
{
if (!PageIsEmpty(page) && offnum < maxoff)
offnum = OffsetNumberNext(offnum);
else
{
/* Walk right to the next page with data */
for (;;)
{
/* if we're at end of scan, release the buffer and return */
if (P_RIGHTMOST(opaque))
{
_bt_relbuf(rel, *bufP);
ItemPointerSetInvalid(current);
*bufP = so->btso_curbuf = InvalidBuffer;
return false;
}
/* step right one page */
blkno = opaque->btpo_next;
_bt_relbuf(rel, *bufP);
*bufP = _bt_getbuf(rel, blkno, BT_READ);
page = BufferGetPage(*bufP);
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
if (!P_IGNORE(opaque))
{
maxoff = PageGetMaxOffsetNumber(page);
/* done if it's not empty */
offnum = P_FIRSTDATAKEY(opaque);
if (!PageIsEmpty(page) && offnum <= maxoff)
break;
}
}
}
}
else
/* backwards scan */
{
if (offnum > P_FIRSTDATAKEY(opaque))
offnum = OffsetNumberPrev(offnum);
else
{
/*
* Walk left to the next page with data. This is much more
* complex than the walk-right case because of the possibility
* that the page to our left splits while we are in flight to
* it, plus the possibility that the page we were on gets
* deleted after we leave it. See nbtree/README for details.
*/
for (;;)
{
*bufP = _bt_walk_left(rel, *bufP);
/* if we're at end of scan, return failure */
if (*bufP == InvalidBuffer)
{
ItemPointerSetInvalid(current);
so->btso_curbuf = InvalidBuffer;
return false;
}
page = BufferGetPage(*bufP);
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
/*
* Okay, we managed to move left to a non-deleted page.
* Done if it's not half-dead and not empty. Else loop
* back and do it all again.
*/
//.........这里部分代码省略.........
开发者ID:sunyangkobe,项目名称:cscd43,代码行数:101,代码来源:nbtsearch.c
示例4: readindex
Datum
readindex(PG_FUNCTION_ARGS)
{
FuncCallContext *funcctx;
readindexinfo *info;
MIRROREDLOCK_BUFMGR_DECLARE;
if (SRF_IS_FIRSTCALL())
{
Oid irelid = PG_GETARG_OID(0);
TupleDesc tupdesc;
MemoryContext oldcontext;
AttrNumber outattnum;
Relation irel;
TupleDesc itupdesc;
int i;
AttrNumber attno;
irel = index_open(irelid, AccessShareLock);
itupdesc = RelationGetDescr(irel);
outattnum = FIXED_COLUMN + itupdesc->natts;
funcctx = SRF_FIRSTCALL_INIT();
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
tupdesc = CreateTemplateTupleDesc(outattnum, false);
attno = 1;
TupleDescInitEntry(tupdesc, attno++, "ictid", TIDOID, -1, 0);
TupleDescInitEntry(tupdesc, attno++, "hctid", TIDOID, -1, 0);
TupleDescInitEntry(tupdesc, attno++, "aotid", TEXTOID, -1, 0);
TupleDescInitEntry(tupdesc, attno++, "istatus", TEXTOID, -1, 0);
TupleDescInitEntry(tupdesc, attno++, "hstatus", TEXTOID, -1, 0);
for (i = 0; i < itupdesc->natts; i++)
{
Form_pg_attribute attr = itupdesc->attrs[i];
TupleDescInitEntry(tupdesc, attno++, NameStr(attr->attname), attr->atttypid, attr->atttypmod, 0);
}
funcctx->tuple_desc = BlessTupleDesc(tupdesc);
info = (readindexinfo *) palloc(sizeof(readindexinfo));
funcctx->user_fctx = (void *) info;
info->outattnum = outattnum;
info->irel = irel;
info->hrel = relation_open(irel->rd_index->indrelid, AccessShareLock);
if (info->hrel->rd_rel != NULL &&
(info->hrel->rd_rel->relstorage == 'a' ||
info->hrel->rd_rel->relstorage == 'c'))
{
relation_close(info->hrel, AccessShareLock);
info->hrel = NULL;
}
info->num_pages = RelationGetNumberOfBlocks(irel);
info->blkno = BTREE_METAPAGE + 1;
info->page = NULL;
MemoryContextSwitchTo(oldcontext);
}
funcctx = SRF_PERCALL_SETUP();
info = (readindexinfo *) funcctx->user_fctx;
while (info->blkno < info->num_pages)
{
Datum values[255];
bool nulls[255];
ItemPointerData itid;
HeapTuple tuple;
Datum result;
if (info->page == NULL)
{
MIRROREDLOCK_BUFMGR_LOCK;
info->buf = ReadBuffer(info->irel, info->blkno);
info->page = BufferGetPage(info->buf);
info->opaque = (BTPageOpaque) PageGetSpecialPointer(info->page);
info->minoff = P_FIRSTDATAKEY(info->opaque);
info->maxoff = PageGetMaxOffsetNumber(info->page);
info->offnum = info->minoff;
MIRROREDLOCK_BUFMGR_UNLOCK;
}
if (!P_ISLEAF(info->opaque) || info->offnum > info->maxoff)
{
ReleaseBuffer(info->buf);
info->page = NULL;
info->blkno++;
continue;
}
MemSet(nulls, false, info->outattnum * sizeof(bool));
ItemPointerSet(&itid, info->blkno, info->offnum);
values[0] = ItemPointerGetDatum(&itid);
readindextuple(info, values, nulls);
info->offnum = OffsetNumberNext(info->offnum);
tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
result = HeapTupleGetDatum(tuple);
//.........这里部分代码省略.........
开发者ID:BenjaminYu,项目名称:gpdb,代码行数:101,代码来源:indexscan.c
示例5: _bt_validate_tid
/*
* For a newly inserted heap tid, check if an entry with this tid
* already exists in a unique index. If it does, abort the inserting
* transaction.
*/
static void
_bt_validate_tid(Relation irel, ItemPointer h_tid)
{
MIRROREDLOCK_BUFMGR_DECLARE;
BlockNumber blkno;
BlockNumber num_pages;
Buffer buf;
Page page;
BTPageOpaque opaque;
IndexTuple itup;
OffsetNumber maxoff,
minoff,
offnum;
elog(DEBUG1, "validating tid (%d,%d) for index (%s)",
ItemPointerGetBlockNumber(h_tid), ItemPointerGetOffsetNumber(h_tid),
RelationGetRelationName(irel));
blkno = BTREE_METAPAGE + 1;
num_pages = RelationGetNumberOfBlocks(irel);
MIRROREDLOCK_BUFMGR_LOCK;
for (; blkno < num_pages; blkno++)
{
buf = ReadBuffer(irel, blkno);
page = BufferGetPage(buf);
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
if (!PageIsNew(page))
_bt_checkpage(irel, buf);
if (P_ISLEAF(opaque))
{
minoff = P_FIRSTDATAKEY(opaque);
maxoff = PageGetMaxOffsetNumber(page);
for (offnum = minoff;
offnum <= maxoff;
offnum = OffsetNumberNext(offnum))
{
itup = (IndexTuple) PageGetItem(page,
PageGetItemId(page, offnum));
if (ItemPointerEquals(&itup->t_tid, h_tid))
{
Form_pg_attribute key_att = RelationGetDescr(irel)->attrs[0];
Oid key = InvalidOid;
bool isnull;
if (key_att->atttypid == OIDOID)
{
key = DatumGetInt32(
index_getattr(itup, 1, RelationGetDescr(irel), &isnull));
elog(ERROR, "found tid (%d,%d), %s (%d) already in index (%s)",
ItemPointerGetBlockNumber(h_tid), ItemPointerGetOffsetNumber(h_tid),
NameStr(key_att->attname), key, RelationGetRelationName(irel));
}
else
{
elog(ERROR, "found tid (%d,%d) already in index (%s)",
ItemPointerGetBlockNumber(h_tid), ItemPointerGetOffsetNumber(h_tid),
RelationGetRelationName(irel));
}
}
}
}
ReleaseBuffer(buf);
}
MIRROREDLOCK_BUFMGR_UNLOCK;
}
开发者ID:LJoNe,项目名称:gpdb,代码行数:71,代码来源:nbtree.c
示例6: btvacuumpage
//.........这里部分代码省略.........
int ndeletable;
OffsetNumber offnum,
minoff,
maxoff;
/*
* Trade in the initial read lock for a super-exclusive write lock on
* this page. We must get such a lock on every leaf page over the
* course of the vacuum scan, whether or not it actually contains any
* deletable tuples --- see nbtree/README.
*/
LockBuffer(buf, BUFFER_LOCK_UNLOCK);
LockBufferForCleanup(buf);
/*
* Check whether we need to recurse back to earlier pages. What we
* are concerned about is a page split that happened since we started
* the vacuum scan. If the split moved some tuples to a lower page
* then we might have missed 'em. If so, set up for tail recursion.
* (Must do this before possibly clearing btpo_cycleid below!)
*/
if (vstate->cycleid != 0 &&
opaque->btpo_cycleid == vstate->cycleid &&
!(opaque->btpo_flags & BTP_SPLIT_END) &&
!P_RIGHTMOST(opaque) &&
opaque->btpo_next < orig_blkno)
recurse_to = opaque->btpo_next;
/*
* Scan over all items to see which ones need deleted according to the
* callback function.
*/
ndeletable = 0;
minoff = P_FIRSTDATAKEY(opaque);
maxoff = PageGetMaxOffsetNumber(page);
if (callback)
{
for (offnum = minoff;
offnum <= maxoff;
offnum = OffsetNumberNext(offnum))
{
IndexTuple itup;
ItemPointer htup;
itup = (IndexTuple) PageGetItem(page,
PageGetItemId(page, offnum));
htup = &(itup->t_tid);
if (callback(htup, callback_state))
deletable[ndeletable++] = offnum;
}
}
/*
* Apply any needed deletes. We issue just one _bt_delitems() call
* per page, so as to minimize WAL traffic.
*/
if (ndeletable > 0)
{
_bt_delitems(rel, buf, deletable, ndeletable, true);
stats->tuples_removed += ndeletable;
/* must recompute maxoff */
maxoff = PageGetMaxOffsetNumber(page);
}
else
{
/*
开发者ID:LJoNe,项目名称:gpdb,代码行数:67,代码来源:nbtree.c
示例7: _bt_parent_deletion_safe
/*
* Subroutine to pre-check whether a page deletion is safe, that is, its
* parent page would be left in a valid or deletable state.
*
* "target" is the page we wish to delete, and "stack" is a search stack
* leading to it (approximately). Note that we will update the stack
* entry(s) to reflect current downlink positions --- this is harmless and
* indeed saves later search effort in _bt_pagedel.
*
* Note: it's OK to release page locks after checking, because a safe
* deletion can't become unsafe due to concurrent activity. A non-rightmost
* page cannot become rightmost unless there's a concurrent page deletion,
* but only VACUUM does page deletion and we only allow one VACUUM on an index
* at a time. An only child could acquire a sibling (of the same parent) only
* by being split ... but that would make it a non-rightmost child so the
* deletion is still safe.
*/
static bool
_bt_parent_deletion_safe(Relation rel, BlockNumber target, BTStack stack)
{
BlockNumber parent;
OffsetNumber poffset,
maxoff;
Buffer pbuf;
Page page;
BTPageOpaque opaque;
MIRROREDLOCK_BUFMGR_MUST_ALREADY_BE_HELD;
/*
* In recovery mode, assume the deletion being replayed is valid. We
* can't always check it because we won't have a full search stack, and we
* should complain if there's a problem, anyway.
*/
if (InRecovery)
return true;
/* Locate the parent's downlink (updating the stack entry if needed) */
ItemPointerSet(&(stack->bts_btentry.t_tid), target, P_HIKEY);
pbuf = _bt_getstackbuf(rel, stack, BT_READ);
if (pbuf == InvalidBuffer)
elog(ERROR, "failed to re-find parent key in index \"%s\" for deletion target page %u",
RelationGetRelationName(rel), target);
parent = stack->bts_blkno;
poffset = stack->bts_offset;
page = BufferGetPage(pbuf);
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
maxoff = PageGetMaxOffsetNumber(page);
/*
* If the target is the rightmost child of its parent, then we can't
* delete, unless it's also the only child.
*/
if (poffset >= maxoff)
{
/* It's rightmost child... */
if (poffset == P_FIRSTDATAKEY(opaque))
{
/*
* It's only child, so safe if parent would itself be removable.
* We have to check the parent itself, and then recurse to test
* the conditions at the parent's parent.
*/
if (P_RIGHTMOST(opaque) || P_ISROOT(opaque))
{
_bt_relbuf(rel, pbuf);
return false;
}
_bt_relbuf(rel, pbuf);
return _bt_parent_deletion_safe(rel, parent, stack->bts_parent);
}
else
{
/* Unsafe to delete */
_bt_relbuf(rel, pbuf);
return false;
}
}
else
{
/* Not rightmost child, so safe to delete */
_bt_relbuf(rel, pbuf);
return true;
}
}
开发者ID:50wu,项目名称:gpdb,代码行数:87,代码来源:nbtpage.c
示例8: _bt_binsrch
/*
* _bt_binsrch() -- Do a binary search for a key on a particular page.
*
* The passed scankey must be an insertion-type scankey (see nbtree/README),
* but it can omit the rightmost column(s) of the index.
*
* When nextkey is false (the usual case), we are looking for the first
* item >= scankey. When nextkey is true, we are looking for the first
* item strictly greater than scankey.
*
* On a leaf page, _bt_binsrch() returns the OffsetNumber of the first
* key >= given scankey, or > scankey if nextkey is true. (NOTE: in
* particular, this means it is possible to return a value 1 greater than the
* number of keys on the page, if the scankey is > all keys on the page.)
*
* On an internal (non-leaf) page, _bt_binsrch() returns the OffsetNumber
* of the last key < given scankey, or last key <= given scankey if nextkey
* is true. (Since _bt_compare treats the first data key of such a page as
* minus infinity, there will be at least one key < scankey, so the result
* always points at one of the keys on the page.) This key indicates the
* right place to descend to be sure we find all leaf keys >= given scankey
* (or leaf keys > given scankey when nextkey is true).
*
* This procedure is not responsible for walking right, it just examines
* the given page. _bt_binsrch() has no lock or refcount side effects
* on the buffer.
*/
OffsetNumber
_bt_binsrch(Relation rel,
Buffer buf,
int keysz,
ScanKey scankey,
bool nextkey)
{
Page page;
BTPageOpaque opaque;
OffsetNumber low,
high;
int32 result,
cmpval;
page = BufferGetPage(buf);
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
low = P_FIRSTDATAKEY(opaque);
high = PageGetMaxOffsetNumber(page);
/*
* If there are no keys on the page, return the first available slot. Note
* this covers two cases: the page is really empty (no keys), or it
* contains only a high key. The latter case is possible after vacuuming.
* This can never happen on an internal page, however, since they are
* never empty (an internal page must have children).
*/
if (high < low)
return low;
/*
* Binary search to find the first key on the page >= scan key, or first
* key > scankey when nextkey is true.
*
* For nextkey=false (cmpval=1), the loop invariant is: all slots before
* 'low' are < scan key, all slots at or after 'high' are >= scan key.
*
* For nextkey=true (cmpval=0), the loop invariant is: all slots before
* 'low' are <= scan key, all slots at or after 'high' are > scan key.
*
* We can fall out when high == low.
*/
high++; /* establish the loop invariant for high */
cmpval = nextkey ? 0 : 1; /* select comparison value */
while (high > low)
{
OffsetNumber mid = low + ((high - low) / 2);
/* We have low <= mid < high, so mid points at a real slot */
result = _bt_compare(rel, keysz, scankey, page, mid);
if (result >= cmpval)
low = mid + 1;
else
high = mid;
}
/*
* At this point we have high == low, but be careful: they could point
* past the last slot on the page.
*
* On a leaf page, we always return the first key >= scan key (resp. >
* scan key), which could be the last slot + 1.
*/
if (P_ISLEAF(opaque))
return low;
/*
* On a non-leaf page, return the last key < scan key (resp. <= scan key).
* There must be one if _bt_compare() is playing by the rules.
//.........这里部分代码省略.........
开发者ID:hasegaw,项目名称:postgresql,代码行数:101,代码来源:nbtsearch.c
示例9: _bt_get_endpoint
/*
* _bt_get_endpoint() -- Find the first or last page on a given tree level
*
* If the index is empty, we will return InvalidBuffer; any other failure
* condition causes ereport(). We will not return a dead page.
*
* The returned buffer is pinned and read-locked.
*/
Buffer
_bt_get_endpoint(Relation rel, uint32 level, bool rightmost)
{
Buffer buf;
Page page;
BTPageOpaque opaque;
OffsetNumber offnum;
BlockNumber blkno;
IndexTuple itup;
/*
* If we are looking for a leaf page, okay to descend from fast root;
* otherwise better descend from true root. (There is no point in being
* smarter about intermediate levels.)
*/
if (level == 0)
buf = _bt_getroot(rel, BT_READ);
else
buf = _bt_gettrueroot(rel);
if (!BufferIsValid(buf))
return InvalidBuffer;
page = BufferGetPage(buf);
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
for (;;)
{
/*
* If we landed on a deleted page, step right to find a live page
* (there must be one). Also, if we want the rightmost page, step
* right if needed to get to it (this could happen if the page split
* since we obtained a pointer to it).
*/
while (P_IGNORE(opaque) ||
(rightmost && !P_RIGHTMOST(opaque)))
{
blkno = opaque->btpo_next;
if (blkno == P_NONE)
elog(ERROR, "fell off the end of index \"%s\"",
RelationGetRelationName(rel));
buf = _bt_relandgetbuf(rel, buf, blkno, BT_READ);
page = BufferGetPage(buf);
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
}
/* Done? */
if (opaque->btpo.level == level)
break;
if (opaque->btpo.level < level)
elog(ERROR, "btree level %u not found in index \"%s\"",
level, RelationGetRelationName(rel));
/* Descend to leftmost or rightmost child page */
if (rightmost)
offnum = PageGetMaxOffsetNumber(page);
else
offnum = P_FIRSTDATAKEY(opaque);
itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, offnum));
blkno = ItemPointerGetBlockNumber(&(itup->t_tid));
buf = _bt_relandgetbuf(rel, buf, blkno, BT_READ);
page = BufferGetPage(buf);
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
}
return buf;
}
开发者ID:hasegaw,项目名称:postgresql,代码行数:77,代码来源:nbtsearch.c
示例10: BTReaderInit
/**
* @brief Read the left-most leaf page by walking down on index tree structure
* from root node.
*
* Process flow
* -# Open index file and read meta page
* -# Get block number of root page
* -# Read "fast root" page
* -# Read left child page until reaching left-most leaf page
*
* After calling this function, the members of BTReader are the following:
* - smgr : Smgr relation of the existing index file.
* - blkno : block number of left-most leaf page. If there is no leaf page,
* InvalidBlockNumber is set.
* - offnum : InvalidOffsetNumber is set.
* - page : Left-most leaf page, or undefined if no leaf page.
*
* @param reader [in/out] B-Tree index reader
* @return true iff there are some tuples
*/
static bool
BTReaderInit(BTReader *reader, Relation rel)
{
BTPageOpaque metaopaque;
BTMetaPageData *metad;
BTPageOpaque opaque;
BlockNumber blkno;
/*
* HACK: We cannot use smgropen because smgrs returned from it
* will be closed automatically when we assign a new file node.
*
* XXX: It might be better to open the previous relfilenode with
* smgropen *after* RelationSetNewRelfilenode.
*/
memset(&reader->smgr, 0, sizeof(reader->smgr));
#if PG_VERSION_NUM >= 90100
reader->smgr.smgr_rnode.node = rel->rd_node;
reader->smgr.smgr_rnode.backend =
rel->rd_backend == MyBackendId ? MyBackendId : InvalidBackendId;
#else
reader->smgr.smgr_rnode = rel->rd_node;
#endif
reader->smgr.smgr_which = 0; /* md.c */
reader->blkno = InvalidBlockNumber;
reader->offnum = InvalidOffsetNumber;
reader->page = palloc(BLCKSZ);
/*
* Read meta page and check sanity of it.
*
* XXX: It might be better to do REINDEX against corrupted indexes
* instead of raising errors because we've spent long time for data
* loading...
*/
BTReaderReadPage(reader, BTREE_METAPAGE);
metaopaque = (BTPageOpaque) PageGetSpecialPointer(reader->page);
metad = BTPageGetMeta(reader->page);
if (!(metaopaque->btpo_flags & BTP_META) ||
metad->btm_magic != BTREE_MAGIC)
ereport(ERROR,
(errcode(ERRCODE_INDEX_CORRUPTED),
errmsg("index \"%s\" is not a reader",
RelationGetRelationName(rel))));
if (metad->btm_version != BTREE_VERSION)
ereport(ERROR,
(errcode(ERRCODE_INDEX_CORRUPTED),
errmsg("version mismatch in index \"%s\": file version %d,"
" code version %d",
RelationGetRelationName(rel),
metad->btm_version, BTREE_VERSION)));
if (metad->btm_root == P_NONE)
{
/* No root page; We ignore the index in the subsequent build. */
reader->blkno = InvalidBlockNumber;
return false;
}
/* Go to the fast root page. */
blkno = metad->btm_fastroot;
BTReaderReadPage(reader, blkno);
opaque = (BTPageOpaque) PageGetSpecialPointer(reader->page);
/* Walk down to the left-most leaf page */
while (!P_ISLEAF(opaque))
{
ItemId firstid;
IndexTuple itup;
/* Get the block number of the left child */
firstid = PageGetItemId(reader->page, P_FIRSTDATAKEY(opaque));
itup = (IndexTuple) PageGetItem(reader->page, firstid);
blkno = ItemPointerGetBlockNumber(&(itup->t_tid));
/* Go down to children */
for (;;)
//.........这里部分代码省略.........
开发者ID:chuongnn,项目名称:pg_bulkload,代码行数:101,代码来源:pg_btree.c
示例11: btree_xlog_split
static void
btree_xlog_split(bool onleft, bool isroot, XLogReaderState *record)
{
XLogRecPtr lsn = record->EndRecPtr;
xl_btree_split *xlrec = (xl_btree_split *) XLogRecGetData(record);
bool isleaf = (xlrec->level == 0);
Buffer lbuf;
Buffer rbuf;
Page rpage;
BTPageOpaque ropaque;
char *datapos;
Size datalen;
Item left_hikey = NULL;
Size left_hikeysz = 0;
BlockNumber leftsib;
BlockNumber rightsib;
BlockNumber rnext;
XLogRecGetBlockTag(record, 0, NULL, NULL, &leftsib);
XLogRecGetBlockTag(record, 1, NULL, NULL, &rightsib);
if (!XLogRecGetBlockTag(record, 2, NULL, NULL, &rnext))
rnext = P_NONE;
/*
* Clear the incomplete split flag on the left sibling of the child page
* this is a downlink for. (Like in btree_xlog_insert, this can be done
* before locking the other pages)
*/
if (!isleaf)
_bt_clear_incomplete_split(record, 3);
/* Reconstruct right (new) sibling page from scratch */
rbuf = XLogInitBufferForRedo(record, 1);
datapos = XLogRecGetBlockData(record, 1, &datalen);
rpage = (Page) BufferGetPage(rbuf);
_bt_pageinit(rpage, BufferGetPageSize(rbuf));
ropaque = (BTPageOpaque) PageGetSpecialPointer(rpage);
ropaque->btpo_prev = leftsib;
ropaque->btpo_next = rnext;
ropaque->btpo.level = xlrec->level;
ropaque->btpo_flags = isleaf ? BTP_LEAF : 0;
ropaque->btpo_cycleid = 0;
_bt_restore_page(rpage, datapos, datalen);
/*
* On leaf level, the high key of the left page is equal to the first key
* on the right page.
*/
if (isleaf)
{
ItemId hiItemId = PageGetItemId(rpage, P_FIRSTDATAKEY(ropaque));
left_hikey = PageGetItem(rpage, hiItemId);
left_hikeysz = ItemIdGetLength(hiItemId);
}
PageSetLSN(rpage, lsn);
MarkBufferDirty(rbuf);
/* don't release the buffer yet; we touch right page's first item below */
/* Now reconstruct left (original) sibling page */
if (XLogReadBufferForRedo(record, 0, &lbuf) == BLK_NEEDS_REDO)
{
/*
* To retain the same physical order of the tuples that they had, we
* initialize a temporary empty page for the left page and add all the
* items to that in item number order. This mirrors how _bt_split()
* works. It's not strictly required to retain the same physical
* order, as long as the items are in the correct item number order,
* but it helps debugging. See also _bt_restore_page(), which does
* the same for the right page.
*/
Page lpage = (Page) BufferGetPage(lbuf);
BTPageOpaque lopaque = (BTPageOpaque) PageGetSpecialPointer(lpage);
OffsetNumber off;
Item newitem = NULL;
Size newitemsz = 0;
Page newlpage;
OffsetNumber leftoff;
datapos = XLogRecGetBlockData(record, 0, &datalen);
if (onleft)
{
newitem = (Item) datapos;
newitemsz = MAXALIGN(IndexTupleSize(newitem));
datapos += newitemsz;
datalen -= newitemsz;
}
/* Extract left hikey and its size (assuming 16-bit alignment) */
if (!isleaf)
{
left_hikey = (Item) datapos;
left_hikeysz = MAXALIGN(IndexTupleSize(left_hikey));
datapos += left_hikeysz;
//.........这里部分代码省略.........
开发者ID:JiannengSun,项目名称:postgres,代码行数:101,代码来源:nbtxlog.c
示例12: readindex
//.........这里部分代码省略.........
funcctx->user_fctx = (void *) info;
info->outattnum = outattnum;
info->ireloid = irelid;
hrel = relation_open(irel->rd_index->indrelid, AccessShareLock);
if (hrel->rd_rel != NULL &&
(hrel->rd_rel->relstorage == 'a' ||
hrel->rd_rel->relstorage == 'c'))
{
relation_close(hrel, AccessShareLock);
hrel = NULL;
info->hreloid = InvalidOid;
}
else
info->hreloid = irel->rd_index->indrelid;
info->num_pages = RelationGetNumberOfBlocks(irel);
info->blkno = BTREE_METAPAGE + 1;
info->page = NULL;
MemoryContextSwitchTo(oldcontext);
}
funcctx = SRF_PERCALL_SETUP();
info = (readindexinfo *) funcctx->user_fctx;
/*
* Open the relations (on first call, we did that above already).
* We unfortunately have to look up the relcache entry on every call,
* because if we store it in the cross-call context, we won't get a
* chance to release it if the function isn't run to completion,
* e.g. because of a LIMIT clause. We only lock the relation on the
* first call, and keep the lock until completion, however.
*/
if (!irel)
irel = index_open(info->ireloid, NoLock);
if (!hrel && info->hreloid != InvalidOid)
hrel = heap_open(info->hreloid, NoLock);
while (info->blkno < info->num_pages)
{
Datum values[255];
bool nulls[255];
ItemPointerData itid;
HeapTuple tuple;
Datum result;
if (info->page == NULL)
{
Buffer buf;
/*
* Make copy of the page, because we cannot hold a buffer pin
* across calls (we wouldn't have a chance to release it, if the
* function isn't run to completion.)
*/
info->page = palloc(BLCKSZ);
MIRROREDLOCK_BUFMGR_LOCK;
buf = ReadBuffer(irel, info->blkno);
memcpy(info->page, BufferGetPage(buf), BLCKSZ);
ReleaseBuffer(buf);
MIRROREDLOCK_BUFMGR_UNLOCK;
info->opaque = (BTPageOpaque) PageGetSpecialPointer(info->page);
info->minoff = P_FIRSTDATAKEY(info->opaque);
info->maxoff = PageGetMaxOffsetNumber(info->page);
info->offnum = info->minoff;
}
if (!P_ISLEAF(info->opaque) || info->offnum > info->maxoff)
{
pfree(info->page);
info->page = NULL;
info->blkno++;
continue;
}
MemSet(nulls, false, info->outattnum * sizeof(bool));
ItemPointerSet(&itid, info->blkno, info->offnum);
values[0] = ItemPointerGetDatum(&itid);
readindextuple(info, irel, hrel, values, nulls);
info->offnum = OffsetNumberNext(info->offnum);
tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
result = HeapTupleGetDatum(tuple);
if (hrel != NULL)
heap_close(hrel, NoLock);
index_close(irel, NoLock);
SRF_RETURN_NEXT(funcctx, result);
}
if (hrel != NULL)
heap_close(hrel, AccessShareLock);
index_close(irel, AccessShareLock);
SRF_RETURN_DONE(funcctx);
}
开发者ID:AnLingm,项目名称:gpdb,代码行数:101,代码来源:indexscan.c
示例13: _bt_pagedel
/*
* _bt_pagedel() -- Delete a page from the b-tree.
*
* This action unlinks the page from the b-tree structure, removing all
* pointers leading to it --- but not touching its own left and right links.
* The page cannot be physically reclaimed right away, since other processes
* may currently be trying to follow links leading to the page; they have to
* be allowed to use its right-link to recover. See nbtree/README.
*
* On entry, the target buffer must be pinned and read-locked. This lock and
* pin will be dropped before exiting.
*
* Returns the number of pages successfully deleted (zero on failure; could
* be more than one if parent blocks were deleted).
*
* NOTE: this leaks memory. Rather than trying to clean up everything
* carefully, it's better to run it in a temp context that can be reset
* frequently.
*/
int
_bt_pagedel(Relation rel, Buffer buf, bool vacuum_full)
{
BlockNumber target,
leftsib,
rightsib,
parent;
OffsetNumber poffset,
maxoff;
uint32 targetlevel,
ilevel;
ItemId itemid;
BTItem targetkey,
btitem;
ScanKey itup_scankey;
BTStack stack;
Buffer lbuf,
rbuf,
pbuf;
bool parent_half_dead;
bool parent_one_child;
bool rightsib_empty;
Buffer metabuf = InvalidBuffer;
Page metapg = NULL;
BTMetaPageData *metad = NULL;
Page page;
BTPageOpaque opaque;
/*
* We can never delete rightmost pages nor root pages. While at it, check
* that page is not already deleted and is empty.
*/
page = BufferGetPage(buf);
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
if (P_RIGHTMOST(opaque) || P_ISROOT(opaque) || P_ISDELETED(opaque) ||
P_FIRSTDATAKEY(opaque) <= PageGetMaxOffsetNumber(page))
{
_bt_relbuf(rel, buf);
return 0;
}
/*
* Save info about page, including a copy of its high key (it must have
* one, being non-rightmost).
*/
target = BufferGetBlockNumber(buf);
targetlevel = opaque->btpo.level;
leftsib = opaque->btpo_prev;
itemid = PageGetItemId(page, P_HIKEY);
targetkey = CopyBTItem((BTItem) PageGetItem(page, itemid));
/*
* We need to get an approximate pointer to the page's parent page. Use
* the standard search mechanism to search for the page's high key; this
* will give us a link to either the current parent or someplace to its
* left (if there are multiple equal high keys). To avoid deadlocks, we'd
* better drop the target page lock first.
*/
_bt_relbuf(rel, buf);
/* we need a scan key to do our search, so build one */
itup_scankey = _bt_mkscankey(rel, &(targetkey->bti_itup));
/* find the leftmost leaf page containing this key */
stack = _bt_search(rel, rel->rd_rel->relnatts, itup_scankey, false,
&lbuf, BT_READ);
/* don't need a pin on that either */
_bt_relbuf(rel, lbuf);
/*
* If we are trying to delete an interior page, _bt_search did more than
* we needed. Locate the stack item pointing to our parent level.
*/
ilevel = 0;
for (;;)
{
if (stack == NULL)
elog(ERROR, "not enough stack items");
if (ilevel == targetlevel)
break;
stack = stack->bts_parent;
ilevel++;
}
//.........这里部分代码省略.........
开发者ID:CraigBryan,项目名称:PostgresqlFun,代码行数:101,代码来源:nbtpage.c
示例14: bt_check_keys
/*
* Test whether an indextuple satisfies all the scankey conditions.
*
* If so, copy its TID into scan->xs_ctup.t_self, and return TRUE.
* If not, return FALSE (xs_ctup is not changed).
*
* If the tuple fails to pass the qual, we also determine whether there's
* any need to continue the scan beyond this tuple, and set *continuescan
* accordingly. See comments for bt_preproc_keys(), above, about how
* this is done.
*
* scan: index scan descriptor (containing a search-type scankey)
* page: buffer page containing index tuple
* offnum: offset number of index tuple (must be a valid item!)
* dir: direction we are scanning in
* continuescan: output parameter (will be set correctly in all cases)
*/
bool
bt_check_keys(
struct index_scan* scan,
page_p page,
item_id_t offnum,
enum scandir dir,
bool* continuescan)
{
struct item_id *iid;
bool tuple_valid;
struct index_tuple *tuple;
struct tuple *tupdesc;
struct bt_scan_opaque *so;
int keysz;
int ikey;
struct scankey *key;
iid = PAGE_ITEM_ID(page, offnum);
*continuescan = true; /* default assumption */
/*
* If the scan specifies not to return killed tuples, then we treat a
* killed tuple as not passing the qual. Most of the time, it's a win to
* not bother examining the tuple's index keys, but just return
* immediately with continuescan = true to proceed to the next tuple.
* 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 && ITEMID_DEAD(iid)) {
/* return immediately if there are more tuples on the page */
if (SCANDIR_FORWARD(dir)) {
if (offnum < PAGE_MAX_ITEM_ID(page))
return false;
} else {
struct bt_page_opaque *opaque;
opaque = (struct bt_page_opaque *) PAGE_SPECIAL_PTR(page);
if (offnum > P_FIRSTDATAKEY(opaque))
return false;
}
/*
* OK, we want to check the keys, but we'll return FALSE even if the
* tuple passes the key tests.
*/
tuple_valid = false;
} else
tuple_valid = true;
tuple = (struct index_tuple*) PAGE_GET_ITEM(page, iid);
tupdesc = REL_DESC(scan->indexRelation);
so = (struct bt_scan_opaque*) scan->opaque;
keysz = so->numberOfKeys;
for (key = so->keyData, ikey = 0; ikey < keysz; key++, ikey++) {
datum_t datum;
bool isNull;
datum_t test;
/* row-comparison keys need special processing */
if (key->sk_flags & SK_ROW_HEADER) {
if (bt_check_rowcompare(key, tuple, tupdesc, dir, continuescan))
continue;
return false;
}
datum = index_getattr(tuple, key->sk_attno, tupdesc, &isNull);
if (key->sk_flags & SK_ISNULL) {
/* Handle IS NULL/NOT NULL tests */
if (key->sk_flags & SK_SEARCHNULL) {
if (isNull)
continue; /* tuple satisfies this qual */
} else {
ASSERT(key->sk_flags & SK_SEARCHNOTNULL);
if (!isNull)
continue; /* tuple satisfies this qual */
}
/*
* Tuple fails this qual. If it's a required qual for the current
* scan direction, then we can conclude no further tuples will
* pass, either.
//.........这里部分代码省略.........
开发者ID:colinet,项目名称:sqlix,代码行数:101,代码来源:nbt_utils.c
示例15: _bt_killitems
/*
* _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
* thereon (generally, this should only be called if so->numKilled > 0).
*
* 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_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 an item has moved off the current page due to a split, we'll fail to
* find it and do nothing (this is not an error case --- we assume the item
* will eventually get marked in a future indexscan). Note that because we
* hold pin on the target page continuously from initially reading the items
* until applying this function, VACUUM cannot have deleted any items from
* the page, and so there is no need to search left from the recorded offset.
* (This observation also guarantees that the item is still the right one
* to delete, which might otherwise be questionable since heap TIDs can get
* recycled.)
*/
void _bt_killitems(struct index_scan *scan, bool haveLock)
{
struct bt_scan_opaque *so;
page_p page;
struct bt_page_opaque *opaque;
item_id_t minoff;
item_id_t maxoff;
int i;
bool killedsomething = false;
so = (struct bt_scan_opaque *)scan->opaque;
ASSERT(BUF_VALID(so->currPos.buf));
if (!haveLock)
lock_buf(so->currPos.buf, BT_READ);
page = BUF_PAGE(so->currPos.buf);
opaque = (struct bt_page_opaque *)PAGE_SPECIAL_PTR(page);
minoff = P_FIRSTDATAKEY(opaque);
maxoff = PAGE_MAX_ITEM_ID(page);
for (i = 0; i < so->numKilled; i++) {
int itemIndex = so->killedItems[i];
struct bt_scan_item *kitem = &so->currPos.items[itemIndex];
item_id_t offnum = kitem->indexOffset;
ASSERT(itemIndex >= so->currPos.firstItem
&& itemIndex <= so->currPos.lastItem);
if (offnum < minoff)
continue; /* pure paranoia */
while (offnum <= maxoff) {
struct item_id *iid;
struct index_tuple *ituple;
iid = PAGE_ITEM_ID(page, offnum);
ituple = (struct index_tuple *)PAGE_GET_ITEM(page, iid);
if (item_ptr_eq(&ituple->t_tid, &kitem->heapTid)) {
/* found the item */
ITEMID_MARK_DEAD(iid);
killedsomething = true;
break; /* out of inner search loop */
}
offnum = ITEM_ID_NEXT(offnum);
}
}
/*
* Since this can be redone later if needed, it's treated the same as a
* 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_DEAD, we also set the page's
* BTP_HAS_GARBAGE flag, which is likewise just a hint.
*/
if (killedsomething) {
opaque->btpo_flags |= BTP_HAS_GARBAGE;
set_buf_commit_needs_save(so->currPos.buf);
}
if (!haveLock)
lock_buf(so->currPos.buf, BUF_LOCK_UNLOCK);
/*
* Always reset the scan state, so we don't look for same items on other
* pages.
*/
so->numKilled = 0;
}
开发者ID:colinet,项目名称:sqlix,代码行数:94,代码来源:nbt_utils.c
示例16: _bt_readpage
/*
* _bt_readpage() -- Load data from current index page into so->currPos
*
* Caller must have pinned and read-locked so->currPos.buf; the buffer's state
* is not changed here. Also, currPos.moreLeft and moreRight must be valid;
* they are updated as appropriate. All other fields of so->currPos are
* initialized from scratch here.
*
* We scan the current page starting at offnum and moving in the indicated
* direction. All items matching the scan keys are loaded into currPos.items.
* moreLeft or moreRight (as appropriate) is cleared if _bt_checkkeys reports
* that there can be no more matching tuples in the current scan direction.
*
* Returns true if any matching items found on the page, false if none.
*/
static bool
_bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum)
{
BTScanOpaque so = (BTScanOpaque) scan->opaque;
Page page;
BTPageOpaque opaque;
OffsetNumber minoff;
OffsetNumber maxoff;
int itemIndex;
IndexTuple itup;
bool continuescan;
/* we must have the buffer pinned and locked */
Assert(BufferIsValid(so->currPos.buf));
page = BufferGetPage(so->currPos.buf);
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
minoff = P_FIRSTDATAKEY(opaque);
maxoff = PageGetMaxOffsetNumber(page);
/*
* we must save the page's right-link while scanning it; this tells us
* where to step right to after we're done with these items. There is no
* corresponding need for the left-link, since splits always go right.
*/
so->currPos.nextPage = opaque->btpo_next;
/* initialize tuple workspace to empty */
so->currPos.nextTupleOffset = 0;
if (ScanDirectionIsForward(dir))
{
/* load items[] in ascending order */
itemIndex = 0;
offnum = Max(offnum, minoff);
while (offnum <= maxoff)
{
itup = _bt_checkkeys(scan, page, offnum, dir, &continuescan);
if (itup != NULL)
{
/* tuple passes all scan key conditions, so remember it */
_bt_saveitem(so, itemIndex, offnum, itup);
itemIndex++;
}
if (!continuesc
|
请发表评论