12
12
* Portions Copyright (c) 1994, Regents of the University of California
13
13
*
14
14
* IDENTIFICATION
15
- * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.99 2003/02/23 23:27:21 tgl Exp $
15
+ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.100 2003/02/24 00:57:17 tgl Exp $
16
16
*
17
17
*-------------------------------------------------------------------------
18
18
*/
24
24
#include "catalog/index.h"
25
25
#include "miscadmin.h"
26
26
#include "storage/freespace.h"
27
+ #include "storage/smgr.h"
27
28
28
29
29
30
/* Working state for btbuild and its callback */
@@ -673,11 +674,10 @@ btbulkdelete(PG_FUNCTION_ARGS)
673
674
/* return statistics */
674
675
num_pages = RelationGetNumberOfBlocks (rel );
675
676
676
- result = (IndexBulkDeleteResult * )palloc (sizeof (IndexBulkDeleteResult ));
677
+ result = (IndexBulkDeleteResult * )palloc0 (sizeof (IndexBulkDeleteResult ));
677
678
result -> num_pages = num_pages ;
678
679
result -> num_index_tuples = num_index_tuples ;
679
680
result -> tuples_removed = tuples_removed ;
680
- result -> pages_free = 0 ;/* not computed here */
681
681
682
682
PG_RETURN_POINTER (result );
683
683
}
@@ -746,6 +746,12 @@ btvacuumcleanup(PG_FUNCTION_ARGS)
746
746
pageSpaces [nFreePages ].avail = BLCKSZ - 1 ;
747
747
nFreePages ++ ;
748
748
}
749
+ pages_deleted ++ ;
750
+ }
751
+ else if (P_ISDELETED (opaque ))
752
+ {
753
+ /* Already deleted, but can't recycle yet */
754
+ pages_deleted ++ ;
749
755
}
750
756
else if ((opaque -> btpo_flags & BTP_HALF_DEAD )||
751
757
P_FIRSTDATAKEY (opaque )> PageGetMaxOffsetNumber (page ))
@@ -758,7 +764,10 @@ btvacuumcleanup(PG_FUNCTION_ARGS)
758
764
oldcontext = MemoryContextSwitchTo (mycontext );
759
765
760
766
ndel = _bt_pagedel (rel ,buf ,info -> vacuum_full );
761
- pages_deleted += ndel ;
767
+
768
+ /* count only this page, else may double-count parent */
769
+ if (ndel )
770
+ pages_deleted ++ ;
762
771
763
772
/*
764
773
* During VACUUM FULL it's okay to recycle deleted pages
@@ -786,6 +795,50 @@ btvacuumcleanup(PG_FUNCTION_ARGS)
786
795
_bt_relbuf (rel ,buf );
787
796
}
788
797
798
+ /*
799
+ * During VACUUM FULL, we truncate off any recyclable pages at the
800
+ * end of the index. In a normal vacuum it'd be unsafe to do this
801
+ * except by acquiring exclusive lock on the index and then rechecking
802
+ * all the pages; doesn't seem worth it.
803
+ */
804
+ if (info -> vacuum_full && nFreePages > 0 )
805
+ {
806
+ BlockNumber new_pages = num_pages ;
807
+
808
+ while (nFreePages > 0 &&
809
+ pageSpaces [nFreePages - 1 ].blkno == new_pages - 1 )
810
+ {
811
+ new_pages -- ;
812
+ pages_deleted -- ;
813
+ nFreePages -- ;
814
+ }
815
+ if (new_pages != num_pages )
816
+ {
817
+ int i ;
818
+
819
+ /*
820
+ * Okay to truncate.
821
+ *
822
+ * First, flush any shared buffers for the blocks we intend to
823
+ * delete. FlushRelationBuffers is a bit more than we need for
824
+ * this, since it will also write out dirty buffers for blocks we
825
+ * aren't deleting, but it's the closest thing in bufmgr's API.
826
+ */
827
+ i = FlushRelationBuffers (rel ,new_pages );
828
+ if (i < 0 )
829
+ elog (ERROR ,"btvacuumcleanup: FlushRelationBuffers returned %d" ,
830
+ i );
831
+
832
+ /*
833
+ * Do the physical truncation.
834
+ */
835
+ new_pages = smgrtruncate (DEFAULT_SMGR ,rel ,new_pages );
836
+ rel -> rd_nblocks = new_pages ;/* update relcache immediately */
837
+ rel -> rd_targblock = InvalidBlockNumber ;
838
+ num_pages = new_pages ;
839
+ }
840
+ }
841
+
789
842
/*
790
843
* Update the shared Free Space Map with the info we now have about
791
844
* free space in the index, discarding any old info the map may have.
@@ -797,13 +850,9 @@ btvacuumcleanup(PG_FUNCTION_ARGS)
797
850
798
851
MemoryContextDelete (mycontext );
799
852
800
- if (pages_deleted > 0 )
801
- elog (info -> message_level ,"Index %s: %u pages, deleted %u; %u now free" ,
802
- RelationGetRelationName (rel ),
803
- num_pages ,pages_deleted ,nFreePages );
804
-
805
853
/* update statistics */
806
854
stats -> num_pages = num_pages ;
855
+ stats -> pages_deleted = pages_deleted ;
807
856
stats -> pages_free = nFreePages ;
808
857
809
858
PG_RETURN_POINTER (stats );