* implementation of insert algorithm
*
*
- * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
recptr = XLogInsert(RM_SPGIST_ID, XLOG_SPGIST_ADD_LEAF, rdata);
PageSetLSN(current->page, recptr);
- PageSetTLI(current->page, ThisTimeLineID);
/* update parent only if we actually changed it */
if (xlrec.blknoParent != InvalidBlockNumber)
{
PageSetLSN(parent->page, recptr);
- PageSetTLI(parent->page, ThisTimeLineID);
}
}
recptr = XLogInsert(RM_SPGIST_ID, XLOG_SPGIST_MOVE_LEAFS, rdata);
PageSetLSN(current->page, recptr);
- PageSetTLI(current->page, ThisTimeLineID);
PageSetLSN(npage, recptr);
- PageSetTLI(npage, ThisTimeLineID);
PageSetLSN(parent->page, recptr);
- PageSetTLI(parent->page, ThisTimeLineID);
}
END_CRIT_SECTION();
Page page = BufferGetPage(newLeafBuffer);
PageSetLSN(page, recptr);
- PageSetTLI(page, ThisTimeLineID);
}
if (saveCurrent.buffer != InvalidBuffer)
Page page = BufferGetPage(saveCurrent.buffer);
PageSetLSN(page, recptr);
- PageSetTLI(page, ThisTimeLineID);
}
PageSetLSN(current->page, recptr);
- PageSetTLI(current->page, ThisTimeLineID);
if (parent->buffer != InvalidBuffer)
{
PageSetLSN(parent->page, recptr);
- PageSetTLI(parent->page, ThisTimeLineID);
}
}
recptr = XLogInsert(RM_SPGIST_ID, XLOG_SPGIST_ADD_NODE, rdata);
PageSetLSN(current->page, recptr);
- PageSetTLI(current->page, ThisTimeLineID);
}
END_CRIT_SECTION();
/* we don't bother to check if any of these are redundant */
PageSetLSN(current->page, recptr);
- PageSetTLI(current->page, ThisTimeLineID);
PageSetLSN(parent->page, recptr);
- PageSetTLI(parent->page, ThisTimeLineID);
PageSetLSN(saveCurrent.page, recptr);
- PageSetTLI(saveCurrent.page, ThisTimeLineID);
}
END_CRIT_SECTION();
recptr = XLogInsert(RM_SPGIST_ID, XLOG_SPGIST_SPLIT_TUPLE, rdata);
PageSetLSN(current->page, recptr);
- PageSetTLI(current->page, ThisTimeLineID);
if (newBuffer != InvalidBuffer)
{
PageSetLSN(BufferGetPage(newBuffer), recptr);
- PageSetTLI(BufferGetPage(newBuffer), ThisTimeLineID);
}
}
}
/*
- * Insert one item into the index
+ * Insert one item into the index.
+ *
+ * Returns true on success, false if we failed to complete the insertion
+ * because of conflict with a concurrent insert. In the latter case,
+ * caller should re-call spgdoinsert() with the same args.
*/
-void
+bool
spgdoinsert(Relation index, SpGistState *state,
ItemPointer heapPtr, Datum datum, bool isnull)
{
&isNew);
current.blkno = BufferGetBlockNumber(current.buffer);
}
- else if (parent.buffer == InvalidBuffer ||
- current.blkno != parent.blkno)
+ else if (parent.buffer == InvalidBuffer)
{
+ /* we hold no parent-page lock, so no deadlock is possible */
current.buffer = ReadBuffer(index, current.blkno);
LockBuffer(current.buffer, BUFFER_LOCK_EXCLUSIVE);
}
+ else if (current.blkno != parent.blkno)
+ {
+ /* descend to a new child page */
+ current.buffer = ReadBuffer(index, current.blkno);
+
+ /*
+ * Attempt to acquire lock on child page. We must beware of
+ * deadlock against another insertion process descending from that
+ * page to our parent page (see README). If we fail to get lock,
+ * abandon the insertion and tell our caller to start over. XXX
+ * this could be improved; perhaps it'd be worth sleeping a bit
+ * before giving up?
+ */
+ if (!ConditionalLockBuffer(current.buffer))
+ {
+ ReleaseBuffer(current.buffer);
+ UnlockReleaseBuffer(parent.buffer);
+ return false;
+ }
+ }
else
{
/* inner tuple can be stored on the same page as parent one */
SpGistSetLastUsedPage(index, parent.buffer);
UnlockReleaseBuffer(parent.buffer);
}
+
+ return true;
}