Commit d1b9ee4e authored by Heikki Linnakangas's avatar Heikki Linnakangas

Fix bug in the GiST vacuum's 2nd stage.

We mustn't assume that the IndexVacuumInfo pointer passed to bulkdelete()
stage is still valid in the vacuumcleanup() stage.

Per very pink buildfarm.
parent 7df159a6
...@@ -31,8 +31,6 @@ typedef struct ...@@ -31,8 +31,6 @@ typedef struct
{ {
IndexBulkDeleteResult stats; /* must be first */ IndexBulkDeleteResult stats; /* must be first */
IndexVacuumInfo *info;
/* /*
* These are used to memorize all internal and empty leaf pages in the 1st * These are used to memorize all internal and empty leaf pages in the 1st
* vacuum stage. They are used in the 2nd stage, to delete all the empty * vacuum stage. They are used in the 2nd stage, to delete all the empty
...@@ -46,6 +44,7 @@ typedef struct ...@@ -46,6 +44,7 @@ typedef struct
/* Working state needed by gistbulkdelete */ /* Working state needed by gistbulkdelete */
typedef struct typedef struct
{ {
IndexVacuumInfo *info;
GistBulkDeleteResult *stats; GistBulkDeleteResult *stats;
IndexBulkDeleteCallback callback; IndexBulkDeleteCallback callback;
void *callback_state; void *callback_state;
...@@ -56,8 +55,9 @@ static void gistvacuumscan(IndexVacuumInfo *info, GistBulkDeleteResult *stats, ...@@ -56,8 +55,9 @@ static void gistvacuumscan(IndexVacuumInfo *info, GistBulkDeleteResult *stats,
IndexBulkDeleteCallback callback, void *callback_state); IndexBulkDeleteCallback callback, void *callback_state);
static void gistvacuumpage(GistVacState *vstate, BlockNumber blkno, static void gistvacuumpage(GistVacState *vstate, BlockNumber blkno,
BlockNumber orig_blkno); BlockNumber orig_blkno);
static void gistvacuum_delete_empty_pages(GistBulkDeleteResult *stats); static void gistvacuum_delete_empty_pages(IndexVacuumInfo *info,
static bool gistdeletepage(GistBulkDeleteResult *stats, GistBulkDeleteResult *stats);
static bool gistdeletepage(IndexVacuumInfo *info, GistBulkDeleteResult *stats,
Buffer buffer, OffsetNumber downlink, Buffer buffer, OffsetNumber downlink,
Buffer leafBuffer); Buffer leafBuffer);
...@@ -121,7 +121,7 @@ gistvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats) ...@@ -121,7 +121,7 @@ gistvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats)
* If we saw any empty pages, try to unlink them from the tree so that * If we saw any empty pages, try to unlink them from the tree so that
* they can be reused. * they can be reused.
*/ */
gistvacuum_delete_empty_pages(gist_stats); gistvacuum_delete_empty_pages(info, gist_stats);
/* we don't need the internal and empty page sets anymore */ /* we don't need the internal and empty page sets anymore */
MemoryContextDelete(gist_stats->page_set_context); MemoryContextDelete(gist_stats->page_set_context);
...@@ -183,7 +183,7 @@ gistvacuumscan(IndexVacuumInfo *info, GistBulkDeleteResult *stats, ...@@ -183,7 +183,7 @@ gistvacuumscan(IndexVacuumInfo *info, GistBulkDeleteResult *stats,
stats->empty_leaf_set = intset_create(); stats->empty_leaf_set = intset_create();
/* Set up info to pass down to gistvacuumpage */ /* Set up info to pass down to gistvacuumpage */
stats->info = info; vstate.info = info;
vstate.stats = stats; vstate.stats = stats;
vstate.callback = callback; vstate.callback = callback;
vstate.callback_state = callback_state; vstate.callback_state = callback_state;
...@@ -269,7 +269,7 @@ static void ...@@ -269,7 +269,7 @@ static void
gistvacuumpage(GistVacState *vstate, BlockNumber blkno, BlockNumber orig_blkno) gistvacuumpage(GistVacState *vstate, BlockNumber blkno, BlockNumber orig_blkno)
{ {
GistBulkDeleteResult *stats = vstate->stats; GistBulkDeleteResult *stats = vstate->stats;
IndexVacuumInfo *info = stats->info; IndexVacuumInfo *info = vstate->info;
IndexBulkDeleteCallback callback = vstate->callback; IndexBulkDeleteCallback callback = vstate->callback;
void *callback_state = vstate->callback_state; void *callback_state = vstate->callback_state;
Relation rel = info->index; Relation rel = info->index;
...@@ -456,9 +456,8 @@ restart: ...@@ -456,9 +456,8 @@ restart:
* Scan all internal pages, and try to delete their empty child pages. * Scan all internal pages, and try to delete their empty child pages.
*/ */
static void static void
gistvacuum_delete_empty_pages(GistBulkDeleteResult *stats) gistvacuum_delete_empty_pages(IndexVacuumInfo *info, GistBulkDeleteResult *stats)
{ {
IndexVacuumInfo *info = stats->info;
Relation rel = info->index; Relation rel = info->index;
BlockNumber empty_pages_remaining; BlockNumber empty_pages_remaining;
uint64 blkno; uint64 blkno;
...@@ -552,7 +551,9 @@ gistvacuum_delete_empty_pages(GistBulkDeleteResult *stats) ...@@ -552,7 +551,9 @@ gistvacuum_delete_empty_pages(GistBulkDeleteResult *stats)
gistcheckpage(rel, leafbuf); gistcheckpage(rel, leafbuf);
LockBuffer(buffer, GIST_EXCLUSIVE); LockBuffer(buffer, GIST_EXCLUSIVE);
if (gistdeletepage(stats, buffer, todelete[i] - deleted, leafbuf)) if (gistdeletepage(info, stats,
buffer, todelete[i] - deleted,
leafbuf))
deleted++; deleted++;
LockBuffer(buffer, GIST_UNLOCK); LockBuffer(buffer, GIST_UNLOCK);
...@@ -585,7 +586,7 @@ gistvacuum_delete_empty_pages(GistBulkDeleteResult *stats) ...@@ -585,7 +586,7 @@ gistvacuum_delete_empty_pages(GistBulkDeleteResult *stats)
* prevented it. * prevented it.
*/ */
static bool static bool
gistdeletepage(GistBulkDeleteResult *stats, gistdeletepage(IndexVacuumInfo *info, GistBulkDeleteResult *stats,
Buffer parentBuffer, OffsetNumber downlink, Buffer parentBuffer, OffsetNumber downlink,
Buffer leafBuffer) Buffer leafBuffer)
{ {
...@@ -661,10 +662,10 @@ gistdeletepage(GistBulkDeleteResult *stats, ...@@ -661,10 +662,10 @@ gistdeletepage(GistBulkDeleteResult *stats,
MarkBufferDirty(parentBuffer); MarkBufferDirty(parentBuffer);
PageIndexTupleDelete(parentPage, downlink); PageIndexTupleDelete(parentPage, downlink);
if (RelationNeedsWAL(stats->info->index)) if (RelationNeedsWAL(info->index))
recptr = gistXLogPageDelete(leafBuffer, txid, parentBuffer, downlink); recptr = gistXLogPageDelete(leafBuffer, txid, parentBuffer, downlink);
else else
recptr = gistGetFakeLSN(stats->info->index); recptr = gistGetFakeLSN(info->index);
PageSetLSN(parentPage, recptr); PageSetLSN(parentPage, recptr);
PageSetLSN(leafPage, recptr); PageSetLSN(leafPage, recptr);
......
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