@@ -200,44 +200,47 @@ blinsert(Relation index, Datum *values, bool *isnull,
200200
201201 /*
202202 * At first, try to insert new tuple to the first page in notFullPage
203- * array. If success we don't need to modify the meta page.
203+ * array. If successful, we don't need to modify the meta page.
204204 */
205205 metaBuffer = ReadBuffer (index , BLOOM_METAPAGE_BLKNO );
206206 LockBuffer (metaBuffer , BUFFER_LOCK_SHARE );
207- metaData = BloomPageGetMeta (BufferGetPage (metaBuffer ));
207+ metaData = BloomPageGetMeta (BufferGetPage (metaBuffer , NULL , NULL ,
208+ BGP_NO_SNAPSHOT_TEST ));
208209
209210 if (metaData -> nEnd > metaData -> nStart )
210211 {
211212 Page page ;
212213
213214 blkno = metaData -> notFullPage [metaData -> nStart ];
214-
215215 Assert (blkno != InvalidBlockNumber );
216+
217+ /* Don't hold metabuffer lock while doing insert */
216218 LockBuffer (metaBuffer , BUFFER_LOCK_UNLOCK );
217219
218220 buffer = ReadBuffer (index , blkno );
219221 LockBuffer (buffer , BUFFER_LOCK_EXCLUSIVE );
222+
220223 state = GenericXLogStart (index );
221224 page = GenericXLogRegister (state , buffer , false);
222225
223226 if (BloomPageAddItem (& blstate , page , itup ))
224227 {
228+ /* Success! Apply the change, clean up, and exit */
225229 GenericXLogFinish (state );
226230 UnlockReleaseBuffer (buffer );
227231 ReleaseBuffer (metaBuffer );
228232 MemoryContextSwitchTo (oldCtx );
229233 MemoryContextDelete (insertCtx );
230234 return false;
231235 }
232- else
233- {
234- GenericXLogAbort (state );
235- UnlockReleaseBuffer (buffer );
236- }
236+
237+ /* Didn't fit, must try other pages */
238+ GenericXLogAbort (state );
239+ UnlockReleaseBuffer (buffer );
237240 }
238241 else
239242 {
240- /* First page in notFullPage isn't suitable */
243+ /* No entries in notFullPage */
241244 LockBuffer (metaBuffer , BUFFER_LOCK_UNLOCK );
242245 }
243246
@@ -247,20 +250,30 @@ blinsert(Relation index, Datum *values, bool *isnull,
247250 */
248251 LockBuffer (metaBuffer , BUFFER_LOCK_EXCLUSIVE );
249252
250- state = GenericXLogStart (index );
251- metaPage = GenericXLogRegister (state , metaBuffer , false);
252- metaData = BloomPageGetMeta (metaPage );
253-
254- /*
255- * Iterate over notFullPage array. Skip page we already tried first.
256- */
253+ /* nStart might have changed while we didn't have lock */
257254 nStart = metaData -> nStart ;
258- if (metaData -> nEnd > nStart &&
255+
256+ /* Skip first page if we already tried it above */
257+ if (nStart < metaData -> nEnd &&
259258 blkno == metaData -> notFullPage [nStart ])
260259 nStart ++ ;
261260
262- while (metaData -> nEnd > nStart )
261+ /*
262+ * This loop iterates for each page we try from the notFullPage array, and
263+ * will also initialize a GenericXLogState for the fallback case of having
264+ * to allocate a new page.
265+ */
266+ for (;;)
263267 {
268+ state = GenericXLogStart (index );
269+
270+ /* get modifiable copy of metapage */
271+ metaPage = GenericXLogRegister (state , metaBuffer , false);
272+ metaData = BloomPageGetMeta (metaPage );
273+
274+ if (nStart >= metaData -> nEnd )
275+ break ; /* no more entries in notFullPage array */
276+
264277 blkno = metaData -> notFullPage [nStart ];
265278 Assert (blkno != InvalidBlockNumber );
266279
@@ -270,6 +283,7 @@ blinsert(Relation index, Datum *values, bool *isnull,
270283
271284 if (BloomPageAddItem (& blstate , page , itup ))
272285 {
286+ /* Success! Apply the changes, clean up, and exit */
273287 metaData -> nStart = nStart ;
274288 GenericXLogFinish (state );
275289 UnlockReleaseBuffer (buffer );
@@ -278,41 +292,41 @@ blinsert(Relation index, Datum *values, bool *isnull,
278292 MemoryContextDelete (insertCtx );
279293 return false;
280294 }
281- else
282- {
283- GenericXLogUnregister (state , buffer );
284- UnlockReleaseBuffer (buffer );
285- }
295+
296+ /* Didn't fit, must try other pages */
297+ GenericXLogAbort (state );
298+ UnlockReleaseBuffer (buffer );
286299 nStart ++ ;
287300 }
288301
289- GenericXLogAbort (state );
290-
291302 /*
292303 * Didn't find place to insert in notFullPage array. Allocate new page.
304+ * (XXX is it good to do this while holding ex-lock on the metapage??)
293305 */
294306 buffer = BloomNewBuffer (index );
295307
296- state = GenericXLogStart (index );
297- metaPage = GenericXLogRegister (state , metaBuffer , false);
298- metaData = BloomPageGetMeta (metaPage );
299308 page = GenericXLogRegister (state , buffer , true);
300309 BloomInitPage (page , 0 );
301310
302311 if (!BloomPageAddItem (& blstate , page , itup ))
303312 {
304- /* We shouldn't be here since we're inserting to the empty page */
313+ /* We shouldn't be here since we're inserting to an empty page */
305314 elog (ERROR , "could not add new bloom tuple to empty page" );
306315 }
307316
317+ /* Reset notFullPage array to contain just this new page */
308318 metaData -> nStart = 0 ;
309319 metaData -> nEnd = 1 ;
310320 metaData -> notFullPage [0 ] = BufferGetBlockNumber (buffer );
311321
322+ /* Apply the changes, clean up, and exit */
312323 GenericXLogFinish (state );
313324
314325 UnlockReleaseBuffer (buffer );
315326 UnlockReleaseBuffer (metaBuffer );
316327
328+ MemoryContextSwitchTo (oldCtx );
329+ MemoryContextDelete (insertCtx );
330+
317331 return false;
318332}
0 commit comments