aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/spgist/spginsert.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2013-11-02 16:45:42 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2013-11-02 16:45:42 -0400
commit24ace4053d42e2c48af8c15d598622e488fb9502 (patch)
tree763003210bff179728b91d1cc69b9c335fb102db /src/backend/access/spgist/spginsert.c
parentbffd1ce92cb4e3e44c3c0ff8cdd4a5a2a8be5e3c (diff)
downloadpostgresql-24ace4053d42e2c48af8c15d598622e488fb9502.tar.gz
postgresql-24ace4053d42e2c48af8c15d598622e488fb9502.zip
Retry after buffer locking failure during SPGiST index creation.
The original coding thought this case was impossible, but it can happen if the bgwriter or checkpointer processes decide to write out an index page while creation is still proceeding, leading to a bogus "unexpected spgdoinsert() failure" error. Problem reported by Jonathan S. Katz. Teodor Sigaev
Diffstat (limited to 'src/backend/access/spgist/spginsert.c')
-rw-r--r--src/backend/access/spgist/spginsert.c15
1 files changed, 11 insertions, 4 deletions
diff --git a/src/backend/access/spgist/spginsert.c b/src/backend/access/spgist/spginsert.c
index f4d0fe5a0c2..2a50d87c74b 100644
--- a/src/backend/access/spgist/spginsert.c
+++ b/src/backend/access/spgist/spginsert.c
@@ -45,10 +45,17 @@ spgistBuildCallback(Relation index, HeapTuple htup, Datum *values,
/* Work in temp context, and reset it after each tuple */
oldCtx = MemoryContextSwitchTo(buildstate->tmpCtx);
- /* No concurrent insertions can be happening, so failure is unexpected */
- if (!spgdoinsert(index, &buildstate->spgstate, &htup->t_self,
- *values, *isnull))
- elog(ERROR, "unexpected spgdoinsert() failure");
+ /*
+ * Even though no concurrent insertions can be happening, we still might
+ * get a buffer-locking failure due to bgwriter or checkpointer taking a
+ * lock on some buffer. So we need to be willing to retry. We can flush
+ * any temp data when retrying.
+ */
+ while (!spgdoinsert(index, &buildstate->spgstate, &htup->t_self,
+ *values, *isnull))
+ {
+ MemoryContextReset(buildstate->tmpCtx);
+ }
MemoryContextSwitchTo(oldCtx);
MemoryContextReset(buildstate->tmpCtx);