ptr += sizeof(spgxlogAddLeaf);
leafTuple = ptr; /* the leaf tuple is unaligned, so make a copy to access its header */
memcpy(&leafTupleHdr, leafTuple, sizeof(SpGistLeafTupleData));
if (action == BLK_NEEDS_REDO)
{
page = BufferGetPage(buffer);
/* insert new tuple */ if (xldata->offnumLeaf != xldata->offnumHeadLeaf)
{ /* normal cases, tuple was added by SpGistPageAddNewItem */
addOrReplaceTuple(page, (Item) leafTuple, leafTupleHdr.size,
xldata->offnumLeaf);
/* update head tuple's chain link if needed */ if (xldata->offnumHeadLeaf != InvalidOffsetNumber)
{
SpGistLeafTuple head;
head = (SpGistLeafTuple) PageGetItem(page,
PageGetItemId(page, xldata->offnumHeadLeaf));
Assert(SGLT_GET_NEXTOFFSET(head) == SGLT_GET_NEXTOFFSET(&leafTupleHdr));
SGLT_SET_NEXTOFFSET(head, xldata->offnumLeaf);
}
} else
{ /* replacing a DEAD tuple */
PageIndexTupleDelete(page, xldata->offnumLeaf); if (PageAddItem(page,
(Item) leafTuple, leafTupleHdr.size,
xldata->offnumLeaf, false, false) != xldata->offnumLeaf)
elog(ERROR, "failed to add item of size %u to SPGiST index page",
leafTupleHdr.size);
}
PageSetLSN(page, lsn);
MarkBufferDirty(buffer);
} if (BufferIsValid(buffer))
UnlockReleaseBuffer(buffer);
/* update parent downlink if necessary */ if (xldata->offnumParent != InvalidOffsetNumber)
{ if (XLogReadBufferForRedo(record, 1, &buffer) == BLK_NEEDS_REDO)
{
SpGistInnerTuple tuple;
BlockNumber blknoLeaf;
ptr += sizeof(spgxlogAddNode);
innerTuple = ptr; /* the tuple is unaligned, so make a copy to access its header */
memcpy(&innerTupleHdr, innerTuple, sizeof(SpGistInnerTupleData));
fillFakeState(&state, xldata->stateSrc);
if (!XLogRecHasBlockRef(record, 1))
{ /* update in place */
Assert(xldata->parentBlk == -1); if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO)
{
page = BufferGetPage(buffer);
PageIndexTupleDelete(page, xldata->offnum); if (PageAddItem(page, (Item) innerTuple, innerTupleHdr.size,
xldata->offnum, false, false) != xldata->offnum)
elog(ERROR, "failed to add item of size %u to SPGiST index page",
innerTupleHdr.size);
/* Install new tuple first so redirect is valid */ if (xldata->newPage)
{ /* AddNode is not used for nulls pages */
buffer = XLogInitBufferForRedo(record, 1);
SpGistInitBuffer(buffer, 0);
action = BLK_NEEDS_REDO;
} else
action = XLogReadBufferForRedo(record, 1, &buffer); if (action == BLK_NEEDS_REDO)
{
page = BufferGetPage(buffer);
/* Delete old tuple, replacing it with redirect or placeholder tuple */ if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO)
{
SpGistDeadTuple dt;
PageIndexTupleDelete(page, xldata->offnum); if (PageAddItem(page, (Item) dt, dt->size,
xldata->offnum, false, false) != xldata->offnum)
elog(ERROR, "failed to add item of size %u to SPGiST index page",
dt->size);
if (state.isBuild)
SpGistPageGetOpaque(page)->nPlaceholder++; else
SpGistPageGetOpaque(page)->nRedirection++;
/* *Ifparentisinthissamepage,updateitnow.
*/ if (xldata->parentBlk == 0)
{
SpGistInnerTuple parentTuple;
ptr += sizeof(spgxlogSplitTuple);
prefixTuple = ptr; /* the prefix tuple is unaligned, so make a copy to access its header */
memcpy(&prefixTupleHdr, prefixTuple, sizeof(SpGistInnerTupleData));
ptr += prefixTupleHdr.size;
postfixTuple = ptr; /* postfix tuple is also unaligned */
memcpy(&postfixTupleHdr, postfixTuple, sizeof(SpGistInnerTupleData));
/* insert postfix tuple first to avoid dangling link */ if (!xldata->postfixBlkSame)
{ if (xldata->newPage)
{
buffer = XLogInitBufferForRedo(record, 1); /* SplitTuple is not used for nulls pages */
SpGistInitBuffer(buffer, 0);
action = BLK_NEEDS_REDO;
} else
action = XLogReadBufferForRedo(record, 1, &buffer); if (action == BLK_NEEDS_REDO)
{
page = BufferGetPage(buffer);
PageSetLSN(page, lsn);
MarkBufferDirty(buffer);
} if (BufferIsValid(buffer))
UnlockReleaseBuffer(buffer);
}
/* now handle the original page */ if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO)
{
page = BufferGetPage(buffer);
PageIndexTupleDelete(page, xldata->offnumPrefix); if (PageAddItem(page, (Item) prefixTuple, prefixTupleHdr.size,
xldata->offnumPrefix, false, false) != xldata->offnumPrefix)
elog(ERROR, "failed to add item of size %u to SPGiST index page",
prefixTupleHdr.size);
if (xldata->postfixBlkSame)
addOrReplaceTuple(page, (Item) postfixTuple,
postfixTupleHdr.size,
xldata->offnumPostfix);
PageSetLSN(page, lsn);
MarkBufferDirty(buffer);
} if (BufferIsValid(buffer))
UnlockReleaseBuffer(buffer);
}
innerTuple = ptr; /* the inner tuple is unaligned, so make a copy to access its header */
memcpy(&innerTupleHdr, innerTuple, sizeof(SpGistInnerTupleData));
ptr += innerTupleHdr.size;
/* now ptr points to the list of leaf tuples */
if (xldata->isRootSplit)
{ /* when splitting root, we touch it only in the guise of new inner */
srcBuffer = InvalidBuffer;
srcPage = NULL;
} elseif (xldata->initSrc)
{ /* just re-init the source page */
srcBuffer = XLogInitBufferForRedo(record, 0);
srcPage = (Page) BufferGetPage(srcBuffer);
/* don't update LSN etc till we're done with it */
}
}
/* try to access dest page if any */ if (!XLogRecHasBlockRef(record, 1))
{
destBuffer = InvalidBuffer;
destPage = NULL;
} elseif (xldata->initDest)
{ /* just re-init the dest page */
destBuffer = XLogInitBufferForRedo(record, 1);
destPage = (Page) BufferGetPage(destBuffer);
SpGistInitBuffer(destBuffer,
SPGIST_LEAF | (xldata->storesNulls ? SPGIST_NULLS : 0)); /* don't update LSN etc till we're done with it */
} else
{ /* *Wecouldprobablyreleasethepagelockimmediatelyinthe *full-page-imagecase,butforsafetylet'sholdittilllater.
*/ if (XLogReadBufferForRedo(record, 1, &destBuffer) == BLK_NEEDS_REDO)
destPage = (Page) BufferGetPage(destBuffer); else
destPage = NULL; /* don't do any page updates */
}
/* restore leaf tuples to src and/or dest page */ for (i = 0; i < xldata->nInsert; i++)
{ char *leafTuple;
SpGistLeafTupleData leafTupleHdr;
/* the tuples are not aligned, so must copy to access the size field. */
leafTuple = ptr;
memcpy(&leafTupleHdr, leafTuple, sizeof(SpGistLeafTupleData));
ptr += leafTupleHdr.size;
page = leafPageSelect[i] ? destPage : srcPage; if (page == NULL) continue; /* no need to touch this page */
/* Now update src and dest page LSNs if needed */ if (srcPage != NULL)
{
PageSetLSN(srcPage, lsn);
MarkBufferDirty(srcBuffer);
} if (destPage != NULL)
{
PageSetLSN(destPage, lsn);
MarkBufferDirty(destBuffer);
}
PageSetLSN(page, lsn);
MarkBufferDirty(innerBuffer);
} if (BufferIsValid(innerBuffer))
UnlockReleaseBuffer(innerBuffer);
/* *Nowwecanreleasetheleaf-pagelocks.It'sokaytodothisbefore *updatingtheparentdownlink.
*/ if (BufferIsValid(srcBuffer))
UnlockReleaseBuffer(srcBuffer); if (BufferIsValid(destBuffer))
UnlockReleaseBuffer(destBuffer);
/* update parent downlink, unless we did it above */ if (XLogRecHasBlockRef(record, 3))
{
Buffer parentBuffer;
if (XLogReadBufferForRedo(record, 3, &parentBuffer) == BLK_NEEDS_REDO)
{
SpGistInnerTuple parent;
/* Remove placeholder tuples at end of page */ if (xldata->firstPlaceholder != InvalidOffsetNumber)
{ int max = PageGetMaxOffsetNumber(page);
OffsetNumber *toDelete;
toDelete = palloc(sizeof(OffsetNumber) * max);
for (i = xldata->firstPlaceholder; i <= max; i++)
toDelete[i - xldata->firstPlaceholder] = i;
i = max - xldata->firstPlaceholder + 1;
Assert(opaque->nPlaceholder >= i);
opaque->nPlaceholder -= i;
/* The array is sorted, so can use PageIndexMultiDelete */
PageIndexMultiDelete(page, toDelete, i);
pfree(toDelete);
}
PageSetLSN(page, lsn);
MarkBufferDirty(buffer);
} if (BufferIsValid(buffer))
UnlockReleaseBuffer(buffer);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.