aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/spgist/spgdoinsert.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/access/spgist/spgdoinsert.c')
-rw-r--r--src/backend/access/spgist/spgdoinsert.c34
1 files changed, 30 insertions, 4 deletions
diff --git a/src/backend/access/spgist/spgdoinsert.c b/src/backend/access/spgist/spgdoinsert.c
index 5f6bcdd6b72..1fd331cbdfd 100644
--- a/src/backend/access/spgist/spgdoinsert.c
+++ b/src/backend/access/spgist/spgdoinsert.c
@@ -1836,9 +1836,13 @@ spgSplitNodeAction(Relation index, SpGistState *state,
}
/*
- * 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)
{
@@ -1927,12 +1931,32 @@ spgdoinsert(Relation index, SpGistState *state,
&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 */
@@ -2131,4 +2155,6 @@ spgdoinsert(Relation index, SpGistState *state,
SpGistSetLastUsedPage(index, parent.buffer);
UnlockReleaseBuffer(parent.buffer);
}
+
+ return true;
}