aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/gist/gistscan.c
diff options
context:
space:
mode:
authorTeodor Sigaev <teodor@sigaev.ru>2005-06-27 12:45:23 +0000
committerTeodor Sigaev <teodor@sigaev.ru>2005-06-27 12:45:23 +0000
commite8cab5fe49c45e9dc2990e36ecd6a42bf01dc4bc (patch)
treeb4950c8a1550ce26aa276a157b8680732ae3ac9b /src/backend/access/gist/gistscan.c
parentc3be085ab7a21e01f530357d962fa22f74a637ef (diff)
downloadpostgresql-e8cab5fe49c45e9dc2990e36ecd6a42bf01dc4bc.tar.gz
postgresql-e8cab5fe49c45e9dc2990e36ecd6a42bf01dc4bc.zip
Concurrency for GiST
- full concurrency for insert/update/select/vacuum: - select and vacuum never locks more than one page simultaneously - select (gettuple) hasn't any lock across it's calls - insert never locks more than two page simultaneously: - during search of leaf to insert it locks only one page simultaneously - while walk upward to the root it locked only parent (may be non-direct parent) and child. One of them X-lock, another may be S- or X-lock - 'vacuum full' locks index - improve gistgetmulti - simplify XLOG records Fix bug in index_beginscan_internal: LockRelation may clean rd_aminfo structure, so move GET_REL_PROCEDURE after LockRelation
Diffstat (limited to 'src/backend/access/gist/gistscan.c')
-rw-r--r--src/backend/access/gist/gistscan.c103
1 files changed, 33 insertions, 70 deletions
diff --git a/src/backend/access/gist/gistscan.c b/src/backend/access/gist/gistscan.c
index 34a8de18290..933ca0f6c65 100644
--- a/src/backend/access/gist/gistscan.c
+++ b/src/backend/access/gist/gistscan.c
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/gist/gistscan.c,v 1.58 2005/05/17 03:34:18 neilc Exp $
+ * $PostgreSQL: pgsql/src/backend/access/gist/gistscan.c,v 1.59 2005/06/27 12:45:22 teodor Exp $
*
*-------------------------------------------------------------------------
*/
@@ -24,11 +24,10 @@
static void gistregscan(IndexScanDesc scan);
static void gistdropscan(IndexScanDesc scan);
static void gistadjone(IndexScanDesc scan, int op, BlockNumber blkno,
- OffsetNumber offnum);
-static void adjuststack(GISTSTACK *stk, BlockNumber blkno);
-static void adjustiptr(IndexScanDesc scan, ItemPointer iptr,
- int op, BlockNumber blkno, OffsetNumber offnum);
-static void gistfreestack(GISTSTACK *s);
+ OffsetNumber offnum, XLogRecPtr newlsn, XLogRecPtr oldlsn);
+static void adjustiptr(IndexScanDesc scan, ItemPointer iptr, GISTSearchStack *stk,
+ int op, BlockNumber blkno, OffsetNumber offnum, XLogRecPtr newlsn, XLogRecPtr oldlsn);
+static void gistfreestack(GISTSearchStack *s);
/*
* Whenever we start a GiST scan in a backend, we register it in
@@ -139,7 +138,7 @@ gistmarkpos(PG_FUNCTION_ARGS)
{
IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0);
GISTScanOpaque so;
- GISTSTACK *o,
+ GISTSearchStack *o,
*n,
*tmp;
@@ -156,12 +155,13 @@ gistmarkpos(PG_FUNCTION_ARGS)
/* copy the parent stack from the current item data */
while (n != NULL)
{
- tmp = (GISTSTACK *) palloc(sizeof(GISTSTACK));
- tmp->offset = n->offset;
+ tmp = (GISTSearchStack *) palloc(sizeof(GISTSearchStack));
+ tmp->lsn = n->lsn;
+ tmp->parentlsn = n->parentlsn;
tmp->block = n->block;
- tmp->parent = o;
+ tmp->next = o;
o = tmp;
- n = n->parent;
+ n = n->next;
}
gistfreestack(so->markstk);
@@ -187,7 +187,7 @@ gistrestrpos(PG_FUNCTION_ARGS)
{
IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0);
GISTScanOpaque so;
- GISTSTACK *o,
+ GISTSearchStack *o,
*n,
*tmp;
@@ -204,12 +204,13 @@ gistrestrpos(PG_FUNCTION_ARGS)
/* copy the parent stack from the current item data */
while (n != NULL)
{
- tmp = (GISTSTACK *) palloc(sizeof(GISTSTACK));
- tmp->offset = n->offset;
+ tmp = (GISTSearchStack *) palloc(sizeof(GISTSearchStack));
+ tmp->lsn = n->lsn;
+ tmp->parentlsn = n->parentlsn;
tmp->block = n->block;
- tmp->parent = o;
+ tmp->next = o;
o = tmp;
- n = n->parent;
+ n = n->next;
}
gistfreestack(so->stack);
@@ -253,6 +254,7 @@ gistendscan(PG_FUNCTION_ARGS)
pfree(scan->opaque);
}
+
gistdropscan(scan);
PG_RETURN_VOID();
@@ -331,16 +333,19 @@ ReleaseResources_gist(void)
}
void
-gistadjscans(Relation rel, int op, BlockNumber blkno, OffsetNumber offnum)
+gistadjscans(Relation rel, int op, BlockNumber blkno, OffsetNumber offnum, XLogRecPtr newlsn, XLogRecPtr oldlsn)
{
GISTScanList l;
Oid relid;
+ if ( XLogRecPtrIsInvalid(newlsn) || XLogRecPtrIsInvalid(oldlsn) )
+ return;
+
relid = RelationGetRelid(rel);
for (l = GISTScans; l != NULL; l = l->gsl_next)
{
if (l->gsl_scan->indexRelation->rd_id == relid)
- gistadjone(l->gsl_scan, op, blkno, offnum);
+ gistadjone(l->gsl_scan, op, blkno, offnum, newlsn, oldlsn);
}
}
@@ -358,20 +363,12 @@ static void
gistadjone(IndexScanDesc scan,
int op,
BlockNumber blkno,
- OffsetNumber offnum)
+ OffsetNumber offnum, XLogRecPtr newlsn, XLogRecPtr oldlsn)
{
- GISTScanOpaque so;
-
- adjustiptr(scan, &(scan->currentItemData), op, blkno, offnum);
- adjustiptr(scan, &(scan->currentMarkData), op, blkno, offnum);
-
- so = (GISTScanOpaque) scan->opaque;
+ GISTScanOpaque so = (GISTScanOpaque) scan->opaque ;
- if (op == GISTOP_SPLIT)
- {
- adjuststack(so->stack, blkno);
- adjuststack(so->markstk, blkno);
- }
+ adjustiptr(scan, &(scan->currentItemData), so->stack, op, blkno, offnum, newlsn, oldlsn);
+ adjustiptr(scan, &(scan->currentMarkData), so->markstk, op, blkno, offnum, newlsn, oldlsn);
}
/*
@@ -383,10 +380,10 @@ gistadjone(IndexScanDesc scan,
*/
static void
adjustiptr(IndexScanDesc scan,
- ItemPointer iptr,
+ ItemPointer iptr, GISTSearchStack *stk,
int op,
BlockNumber blkno,
- OffsetNumber offnum)
+ OffsetNumber offnum, XLogRecPtr newlsn, XLogRecPtr oldlsn)
{
OffsetNumber curoff;
GISTScanOpaque so;
@@ -402,7 +399,7 @@ adjustiptr(IndexScanDesc scan,
{
case GISTOP_DEL:
/* back up one if we need to */
- if (curoff >= offnum)
+ if (curoff >= offnum && XLByteEQ(stk->lsn, oldlsn) ) /* the same vesrion of page */
{
if (curoff > FirstOffsetNumber)
{
@@ -421,18 +418,9 @@ adjustiptr(IndexScanDesc scan,
else
so->flags |= GS_MRKBEFORE;
}
+ stk->lsn = newlsn;
}
break;
-
- case GISTOP_SPLIT:
- /* back to start of page on split */
- ItemPointerSet(iptr, blkno, FirstOffsetNumber);
- if (iptr == &(scan->currentItemData))
- so->flags &= ~GS_CURBEFORE;
- else
- so->flags &= ~GS_MRKBEFORE;
- break;
-
default:
elog(ERROR, "Bad operation in GiST scan adjust: %d", op);
}
@@ -440,37 +428,12 @@ adjustiptr(IndexScanDesc scan,
}
}
-/*
- * adjuststack() -- adjust the supplied stack for a split on a page in
- * the index we're scanning.
- *
- * If a page on our parent stack has split, we need to back up to the
- * beginning of the page and rescan it. The reason for this is that
- * the split algorithm for GiSTs doesn't order tuples in any useful
- * way on a single page. This means on that a split, we may wind up
- * looking at some heap tuples more than once. This is handled in the
- * access method update code for heaps; if we've modified the tuple we
- * are looking at already in this transaction, we ignore the update
- * request.
- */
-static void
-adjuststack(GISTSTACK *stk, BlockNumber blkno)
-{
- while (stk != NULL)
- {
- if (stk->block == blkno)
- stk->offset = FirstOffsetNumber;
-
- stk = stk->parent;
- }
-}
-
static void
-gistfreestack(GISTSTACK *s)
+gistfreestack(GISTSearchStack *s)
{
while (s != NULL)
{
- GISTSTACK *p = s->parent;
+ GISTSearchStack *p = s->next;
pfree(s);
s = p;
}