@@ -108,13 +108,6 @@ typedef struct GistBDItem
108108 struct GistBDItem * next ;
109109} GistBDItem ;
110110
111- typedef struct GistBDSItem
112- {
113- BlockNumber blkno ;
114- bool isParent ;
115- struct GistBDSItem * next ;
116- } GistBDSItem ;
117-
118111typedef enum
119112{
120113 NOT_NEED_TO_PROCESS , /* without action */
@@ -164,6 +157,9 @@ gistbulkdelete(IndexVacuumInfo * info, IndexBulkDeleteResult * stats, IndexBulkD
164157 Relation rel = info -> index ;
165158 GistBDItem * stack ,
166159 * ptr ;
160+ BlockNumber recentParent = InvalidBlockNumber ;
161+ List * rescanList = NULL ;
162+ ListCell * cell ;
167163
168164 /* first time through? */
169165 if (stats == NULL )
@@ -256,9 +252,16 @@ gistbulkdelete(IndexVacuumInfo * info, IndexBulkDeleteResult * stats, IndexBulkD
256252 END_CRIT_SECTION ();
257253 }
258254
255+ if (ntodelete == maxoff && recentParent != InvalidBlockNumber &&
256+ (rescanList == NULL || (BlockNumber )llast_int (rescanList ) != recentParent ))
257+ {
258+ /* This page is a candidate to be deleted. Remember it's parent to rescan it later with xlock */
259+ rescanList = lappend_int (rescanList , recentParent );
260+ }
259261 }
260262 else
261263 {
264+ recentParent = stack -> blkno ;
262265 /* check for split proceeded after look at parent */
263266 pushStackIfSplited (page , stack );
264267
@@ -293,5 +296,107 @@ gistbulkdelete(IndexVacuumInfo * info, IndexBulkDeleteResult * stats, IndexBulkD
293296 vacuum_delay_point ();
294297 }
295298
299+
300+ elog (NOTICE ,"Rescan list length %d" , length (rescanList ));
301+ /* rescan inner pages that had empty child pages */
302+ foreach (cell ,rescanList )
303+ {
304+ Buffer buffer ;
305+ Page page ;
306+ OffsetNumber i ,
307+ maxoff ;
308+ IndexTuple idxtuple ;
309+ ItemId iid ;
310+ OffsetNumber todelete [MaxOffsetNumber ];
311+ Buffer buftodelete [MaxOffsetNumber ];
312+ int ntodelete = 0 ;
313+
314+ elog (NOTICE ,"Deleting for inner %d" ,(BlockNumber )lfirst_int (cell ));
315+ buffer = ReadBufferExtended (rel , MAIN_FORKNUM , (BlockNumber )lfirst_int (cell ),
316+ RBM_NORMAL , info -> strategy );
317+ LockBuffer (buffer , GIST_EXCLUSIVE );
318+ gistcheckpage (rel , buffer );
319+ page = (Page ) BufferGetPage (buffer );
320+
321+ Assert (!GistPageIsLeaf (page ));
322+
323+ maxoff = PageGetMaxOffsetNumber (page );
324+
325+ for (i = FirstOffsetNumber ; i <= maxoff ; i = OffsetNumberNext (i ))
326+ {
327+ Buffer leafBuffer ;
328+ Page leafPage ;
329+
330+ iid = PageGetItemId (page , i );
331+ idxtuple = (IndexTuple ) PageGetItem (page , iid );
332+
333+ leafBuffer = ReadBufferExtended (rel , MAIN_FORKNUM , ItemPointerGetBlockNumber (& (idxtuple -> t_tid )),
334+ RBM_NORMAL , info -> strategy );
335+ LockBuffer (leafBuffer , GIST_EXCLUSIVE );
336+ gistcheckpage (rel , leafBuffer );
337+ leafPage = (Page ) BufferGetPage (leafBuffer );
338+
339+ if (PageGetMaxOffsetNumber (leafPage ) == InvalidOffsetNumber
340+ && !(GistFollowRight (leafPage ) || GistPageGetNSN (page ) < GistPageGetNSN (leafPage )))
341+ {
342+ buftodelete [ntodelete ] = leafBuffer ;
343+ todelete [ntodelete ++ ] = i ;
344+ }
345+ else
346+ UnlockReleaseBuffer (leafBuffer );
347+ }
348+
349+ if (ntodelete )
350+ {
351+ START_CRIT_SECTION ();
352+
353+ MarkBufferDirty (buffer );
354+
355+ PageIndexMultiDelete (page , todelete , ntodelete );
356+ GistMarkTuplesDeleted (page );
357+
358+ if (RelationNeedsWAL (rel ))
359+ {
360+ XLogRecPtr recptr ;
361+
362+ recptr = gistXLogUpdate (buffer ,
363+ todelete , ntodelete ,
364+ NULL , 0 , InvalidBuffer );
365+ PageSetLSN (page , recptr );
366+ }
367+ else
368+ PageSetLSN (page , gistGetFakeLSN (rel ));
369+
370+ END_CRIT_SECTION ();
371+
372+ for (i = 0 ; i < ntodelete ; i ++ )
373+ {
374+ Page leafPage = (Page )BufferGetPage (buftodelete [i ]);
375+ PageHeader header = (PageHeader )leafPage ;
376+
377+ header -> pd_prune_xid = GetCurrentTransactionId ();
378+
379+ GistPageSetDeleted (leafPage );
380+ stats -> pages_deleted ++ ;
381+
382+ if (RelationNeedsWAL (rel ))
383+ {
384+ XLogRecPtr recptr ;
385+
386+ recptr = gistXLogSetDeleted (rel -> rd_node , buftodelete [i ], header -> pd_prune_xid );
387+ PageSetLSN (leafPage , recptr );
388+ }
389+ else
390+ PageSetLSN (leafPage , gistGetFakeLSN (rel ));
391+
392+ UnlockReleaseBuffer (buftodelete [i ]);
393+ }
394+ }
395+
396+ UnlockReleaseBuffer (buffer );
397+ }
398+
399+ list_free (rescanList );
400+
296401 return stats ;
297402}
0 commit comments