13
13
#include "postgres.h"
14
14
15
15
#include "access/genam.h"
16
+ #include "bloom.h"
16
17
#include "catalog/storage.h"
17
18
#include "commands/vacuum.h"
18
19
#include "miscadmin.h"
21
22
#include "storage/indexfsm.h"
22
23
#include "storage/lmgr.h"
23
24
24
- #include "bloom.h"
25
25
26
26
/*
27
27
* Bulk deletion of all index entries pointing to a set of heap tuples.
@@ -42,6 +42,7 @@ blbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
42
42
BloomState state ;
43
43
Buffer buffer ;
44
44
Page page ;
45
+ BloomMetaPageData * metaData ;
45
46
GenericXLogState * gxlogState ;
46
47
47
48
if (stats == NULL )
@@ -60,22 +61,27 @@ blbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
60
61
* itupPtr ,
61
62
* itupEnd ;
62
63
64
+ vacuum_delay_point ();
65
+
63
66
buffer = ReadBufferExtended (index ,MAIN_FORKNUM ,blkno ,
64
67
RBM_NORMAL ,info -> strategy );
65
68
66
69
LockBuffer (buffer ,BUFFER_LOCK_EXCLUSIVE );
67
70
gxlogState = GenericXLogStart (index );
68
71
page = GenericXLogRegisterBuffer (gxlogState ,buffer ,0 );
69
72
70
- if (BloomPageIsDeleted (page ))
73
+ /* Ignore empty/deleted pages until blvacuumcleanup() */
74
+ if (PageIsNew (page )|| BloomPageIsDeleted (page ))
71
75
{
72
76
UnlockReleaseBuffer (buffer );
73
77
GenericXLogAbort (gxlogState );
74
- CHECK_FOR_INTERRUPTS ();
75
78
continue ;
76
79
}
77
80
78
- /* Iterate over the tuples */
81
+ /*
82
+ * Iterate over the tuples. itup points to current tuple being
83
+ * scanned, itupPtr points to where to save next non-deleted tuple.
84
+ */
79
85
itup = itupPtr = BloomPageGetTuple (& state ,page ,FirstOffsetNumber );
80
86
itupEnd = BloomPageGetTuple (& state ,page ,
81
87
OffsetNumberNext (BloomPageGetMaxOffset (page )));
@@ -84,36 +90,32 @@ blbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
84
90
/* Do we have to delete this tuple? */
85
91
if (callback (& itup -> heapPtr ,callback_state ))
86
92
{
87
- stats -> tuples_removed += 1 ;
93
+ /* Yes; adjust count of tuples that will be left on page */
88
94
BloomPageGetOpaque (page )-> maxoff -- ;
95
+ stats -> tuples_removed += 1 ;
89
96
}
90
97
else
91
98
{
99
+ /* No; copy it to itupPtr++, but skip copy if not needed */
92
100
if (itupPtr != itup )
93
- {
94
- /*
95
- * If we already delete something before, we have to move
96
- * this tuple backward.
97
- */
98
101
memmove ((Pointer )itupPtr , (Pointer )itup ,
99
102
state .sizeOfBloomTuple );
100
- }
101
- stats -> num_index_tuples ++ ;
102
103
itupPtr = BloomPageGetNextTuple (& state ,itupPtr );
103
104
}
104
105
105
106
itup = BloomPageGetNextTuple (& state ,itup );
106
107
}
107
108
109
+ /* Assert that we counted correctly */
108
110
Assert (itupPtr == BloomPageGetTuple (& state ,page ,
109
111
OffsetNumberNext (BloomPageGetMaxOffset (page ))));
110
112
111
113
/*
112
- * Add page to notFullPage list if we will not mark page as deleted
113
- * and there is a free space on it
114
+ * Add page tonew notFullPage list if we will not mark page as
115
+ *deleted and there is free space on it
114
116
*/
115
117
if (BloomPageGetMaxOffset (page )!= 0 &&
116
- BloomPageGetFreeSpace (& state ,page )> state .sizeOfBloomTuple &&
118
+ BloomPageGetFreeSpace (& state ,page ) >= state .sizeOfBloomTuple &&
117
119
countPage < BloomMetaBlockN )
118
120
notFullPage [countPage ++ ]= blkno ;
119
121
@@ -134,27 +136,26 @@ blbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
134
136
GenericXLogAbort (gxlogState );
135
137
}
136
138
UnlockReleaseBuffer (buffer );
137
- CHECK_FOR_INTERRUPTS ();
138
139
}
139
140
140
- if (countPage > 0 )
141
- {
142
- BloomMetaPageData * metaData ;
143
-
144
- buffer = ReadBuffer (index ,BLOOM_METAPAGE_BLKNO );
145
- LockBuffer (buffer ,BUFFER_LOCK_EXCLUSIVE );
141
+ /*
142
+ * Update the metapage's notFullPage list with whatever we found. Our
143
+ * info could already be out of date at this point, but blinsert() will
144
+ * cope if so.
145
+ */
146
+ buffer = ReadBuffer (index ,BLOOM_METAPAGE_BLKNO );
147
+ LockBuffer (buffer ,BUFFER_LOCK_EXCLUSIVE );
146
148
147
- gxlogState = GenericXLogStart (index );
148
- page = GenericXLogRegisterBuffer (gxlogState ,buffer ,0 );
149
+ gxlogState = GenericXLogStart (index );
150
+ page = GenericXLogRegisterBuffer (gxlogState ,buffer ,0 );
149
151
150
- metaData = BloomPageGetMeta (page );
151
- memcpy (metaData -> notFullPage ,notFullPage ,sizeof (BlockNumber )* countPage );
152
- metaData -> nStart = 0 ;
153
- metaData -> nEnd = countPage ;
152
+ metaData = BloomPageGetMeta (page );
153
+ memcpy (metaData -> notFullPage ,notFullPage ,sizeof (BlockNumber )* countPage );
154
+ metaData -> nStart = 0 ;
155
+ metaData -> nEnd = countPage ;
154
156
155
- GenericXLogFinish (gxlogState );
156
- UnlockReleaseBuffer (buffer );
157
- }
157
+ GenericXLogFinish (gxlogState );
158
+ UnlockReleaseBuffer (buffer );
158
159
159
160
return stats ;
160
161
}
@@ -170,7 +171,6 @@ blvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats)
170
171
Relation index = info -> index ;
171
172
BlockNumber npages ,
172
173
blkno ;
173
- BlockNumber totFreePages ;
174
174
175
175
if (info -> analyze_only )
176
176
return stats ;
@@ -183,7 +183,9 @@ blvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats)
183
183
* statistics.
184
184
*/
185
185
npages = RelationGetNumberOfBlocks (index );
186
- totFreePages = 0 ;
186
+ stats -> num_pages = npages ;
187
+ stats -> pages_free = 0 ;
188
+ stats -> num_index_tuples = 0 ;
187
189
for (blkno = BLOOM_HEAD_BLKNO ;blkno < npages ;blkno ++ )
188
190
{
189
191
Buffer buffer ;
@@ -196,23 +198,20 @@ blvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats)
196
198
LockBuffer (buffer ,BUFFER_LOCK_SHARE );
197
199
page = (Page )BufferGetPage (buffer );
198
200
199
- if (BloomPageIsDeleted (page ))
201
+ if (PageIsNew ( page ) || BloomPageIsDeleted (page ))
200
202
{
201
203
RecordFreeIndexPage (index ,blkno );
202
- totFreePages ++ ;
204
+ stats -> pages_free ++ ;
203
205
}
204
206
else
205
207
{
206
208
stats -> num_index_tuples += BloomPageGetMaxOffset (page );
207
- stats -> estimated_count += BloomPageGetMaxOffset (page );
208
209
}
209
210
210
211
UnlockReleaseBuffer (buffer );
211
212
}
212
213
213
214
IndexFreeSpaceMapVacuum (info -> index );
214
- stats -> pages_free = totFreePages ;
215
- stats -> num_pages = RelationGetNumberOfBlocks (index );
216
215
217
216
return stats ;
218
217
}