Commit b450abd2 authored by Alexander Korotkov's avatar Alexander Korotkov

Remove entry tree root conflict checking from GIN predicate locking

According to README we acquire predicate locks on entry tree leafs and posting
tree roots.  However, when ginFindLeafPage() is going to lock leaf in exclusive
mode, then it checks root for conflicts regardless whether it's a entry or
posting tree.  Assuming that we never place predicate lock on entry tree root
(excluding corner case when root is leaf), this check is redundant.  This
commit removes this check.  Now, root conflict checking is controlled by
separate argument of ginFindLeafPage().

Discussion: https://postgr.es/m/CAPpHfdv7rrDyy%3DMgsaK-L9kk0AH7az0B-mdC3w3p0FSb9uoyEg%40mail.gmail.com
Author: Alexander Korotkov
Backpatch-through: 11
parent 1e504f01
...@@ -72,9 +72,13 @@ ginTraverseLock(Buffer buffer, bool searchMode) ...@@ -72,9 +72,13 @@ ginTraverseLock(Buffer buffer, bool searchMode)
* If 'searchmode' is false, on return stack->buffer is exclusively locked, * If 'searchmode' is false, on return stack->buffer is exclusively locked,
* and the stack represents the full path to the root. Otherwise stack->buffer * and the stack represents the full path to the root. Otherwise stack->buffer
* is share-locked, and stack->parent is NULL. * is share-locked, and stack->parent is NULL.
*
* If 'rootConflictCheck' is true, tree root is checked for serialization
* conflict.
*/ */
GinBtreeStack * GinBtreeStack *
ginFindLeafPage(GinBtree btree, bool searchMode, Snapshot snapshot) ginFindLeafPage(GinBtree btree, bool searchMode,
bool rootConflictCheck, Snapshot snapshot)
{ {
GinBtreeStack *stack; GinBtreeStack *stack;
...@@ -84,7 +88,7 @@ ginFindLeafPage(GinBtree btree, bool searchMode, Snapshot snapshot) ...@@ -84,7 +88,7 @@ ginFindLeafPage(GinBtree btree, bool searchMode, Snapshot snapshot)
stack->parent = NULL; stack->parent = NULL;
stack->predictNumber = 1; stack->predictNumber = 1;
if (!searchMode) if (rootConflictCheck)
CheckForSerializableConflictIn(btree->index, NULL, stack->buffer); CheckForSerializableConflictIn(btree->index, NULL, stack->buffer);
for (;;) for (;;)
......
...@@ -1913,7 +1913,7 @@ ginInsertItemPointers(Relation index, BlockNumber rootBlkno, ...@@ -1913,7 +1913,7 @@ ginInsertItemPointers(Relation index, BlockNumber rootBlkno,
{ {
/* search for the leaf page where the first item should go to */ /* search for the leaf page where the first item should go to */
btree.itemptr = insertdata.items[insertdata.curitem]; btree.itemptr = insertdata.items[insertdata.curitem];
stack = ginFindLeafPage(&btree, false, NULL); stack = ginFindLeafPage(&btree, false, true, NULL);
ginInsertValue(&btree, stack, &insertdata, buildStats); ginInsertValue(&btree, stack, &insertdata, buildStats);
} }
...@@ -1932,7 +1932,7 @@ ginScanBeginPostingTree(GinBtree btree, Relation index, BlockNumber rootBlkno, ...@@ -1932,7 +1932,7 @@ ginScanBeginPostingTree(GinBtree btree, Relation index, BlockNumber rootBlkno,
btree->fullScan = true; btree->fullScan = true;
stack = ginFindLeafPage(btree, true, snapshot); stack = ginFindLeafPage(btree, true, false, snapshot);
return stack; return stack;
} }
...@@ -338,7 +338,7 @@ restartScanEntry: ...@@ -338,7 +338,7 @@ restartScanEntry:
ginPrepareEntryScan(&btreeEntry, entry->attnum, ginPrepareEntryScan(&btreeEntry, entry->attnum,
entry->queryKey, entry->queryCategory, entry->queryKey, entry->queryCategory,
ginstate); ginstate);
stackEntry = ginFindLeafPage(&btreeEntry, true, snapshot); stackEntry = ginFindLeafPage(&btreeEntry, true, false, snapshot);
page = BufferGetPage(stackEntry->buffer); page = BufferGetPage(stackEntry->buffer);
/* ginFindLeafPage() will have already checked snapshot age. */ /* ginFindLeafPage() will have already checked snapshot age. */
...@@ -679,7 +679,7 @@ entryLoadMoreItems(GinState *ginstate, GinScanEntry entry, ...@@ -679,7 +679,7 @@ entryLoadMoreItems(GinState *ginstate, GinScanEntry entry,
OffsetNumberNext(GinItemPointerGetOffsetNumber(&advancePast))); OffsetNumberNext(GinItemPointerGetOffsetNumber(&advancePast)));
} }
entry->btree.fullScan = false; entry->btree.fullScan = false;
stack = ginFindLeafPage(&entry->btree, true, snapshot); stack = ginFindLeafPage(&entry->btree, true, false, snapshot);
/* we don't need the stack, just the buffer. */ /* we don't need the stack, just the buffer. */
entry->buffer = stack->buffer; entry->buffer = stack->buffer;
......
...@@ -195,7 +195,7 @@ ginEntryInsert(GinState *ginstate, ...@@ -195,7 +195,7 @@ ginEntryInsert(GinState *ginstate,
ginPrepareEntryScan(&btree, attnum, key, category, ginstate); ginPrepareEntryScan(&btree, attnum, key, category, ginstate);
stack = ginFindLeafPage(&btree, false, NULL); stack = ginFindLeafPage(&btree, false, false, NULL);
page = BufferGetPage(stack->buffer); page = BufferGetPage(stack->buffer);
if (btree.findItem(&btree, stack)) if (btree.findItem(&btree, stack))
......
...@@ -195,7 +195,8 @@ typedef struct ...@@ -195,7 +195,8 @@ typedef struct
* PostingItem * PostingItem
*/ */
extern GinBtreeStack *ginFindLeafPage(GinBtree btree, bool searchMode, Snapshot snapshot); extern GinBtreeStack *ginFindLeafPage(GinBtree btree, bool searchMode,
bool rootConflictCheck, Snapshot snapshot);
extern Buffer ginStepRight(Buffer buffer, Relation index, int lockmode); extern Buffer ginStepRight(Buffer buffer, Relation index, int lockmode);
extern void freeGinBtreeStack(GinBtreeStack *stack); extern void freeGinBtreeStack(GinBtreeStack *stack);
extern void ginInsertValue(GinBtree btree, GinBtreeStack *stack, extern void ginInsertValue(GinBtree btree, GinBtreeStack *stack,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment